![]() |
Ende von Aufnahme erkennen 'bass.dll'
Hi, ich habe momentan ein Aufnahmeprogramm in der späten Alpha-Phase. Es gibt jedoch noch 2 schwerwiegende Probleme:
1. Wenn ich einen zuvor aufgenommenen Stream wiedergebe, wird das Ende des Streams nicht erkannt und somit bleiben auch die Buttons am Ende falsch (also sozusagen als ob weiterhin wiedergegeben wird) 2. Wenn ich etwas aufgenommen habe, und der Nutzer merkt, dass er an einer bestimmten Stelle was ändern möchte, dann soll an der Position an welcher er sich grade befindet die Aufnahme fortgeführt werden und alles was evt. dahinter schon gesprochen wurde überschrieben/gelöscht werden. Ich habe jetzt mit WaveStream.Position := Trackbar.Position schon definiert wo der Punkt ist ab dem überschieben werden soll. Ab da fehlt mir allerdings die Idee wie ich fortfahren kann. Sorry für so viele Fragen und Threads in so kurzer Zeit, aber es muss ja mal weitergehen bei meinen Programmen ;) Danke schonma, Duck |
Re: Ende von Aufnahme erkennen 'bass.dll'
Stichwort.. SyncProc
Delphi-Quellcode:
wird ausgeführt wenn dein Stream endet
procedure SyncProc(Handle: HSync; Channel, Data: DWORD; User: DWORD); stdcall;
begin // dein Code end; gruss Emil |
Re: Ende von Aufnahme erkennen 'bass.dll'
Hi
Zum Punkt 1. wie ich das sehe/verstehe erkennt bass die Länge der Datei/Stream nicht. Benutzt du den Flag (BASS_STREAM_AUTOFREE)? Und den Channel status kannst du dann mit dem SyncProc oder mit BASS_ChannelIsActive überprüfen. Zum Punkt 2. wie tust du Aufnehmen? Schreibst du das sofort in eine Datei (TFileStream)? RecordProc? Ich denke wir könnten die weiter helfen wen du uns ein wenig Code Zeigen würdest. Du solltest dir auch mal BASS_StreamPutData, BASS_StreamPutFileData anschauen. und du Könntest dir auch mal Bass_Video anschauen da sind einige demos dabei die dich eventuell weiter helfen. |
Re: Ende von Aufnahme erkennen 'bass.dll'
Hallo. Also um mal ein bisschen Code mitzuteilen:
Die Wiedergabe läuft folgendermaßen:
Delphi-Quellcode:
(* PlayButtonClick || Wiedergabe der Aufnahme *)
procedure TRecordForm.PlayExecute(Sender: TObject); var hEndSync: HSYNC; begin case BASS_ChannelIsActive(chan) of BASS_Active_Stopped: begin BASS_ChannelPlay(chan, True); ToggleStatus(1); end; BASS_Active_Playing: begin BASS_ChannelPause(chan); ToggleStatus(2); end; BASS_Active_Paused: begin BASS_ChannelPlay(chan, False); ToggleStatus(1); end; end; // case end; // procedure PlayExecute Beim Aufnehmen sieht es so aus:
Delphi-Quellcode:
(* Aufnahme Start *)
procedure TRecordForm.StartRecording; var vol: Float; i: Integer; Flag: DWord; begin // Aufnahme je nach Aufnahmemodus if OverwriteRadioButton.Checked = True then begin if WaveStream.Size > 0 then begin // alte Aufnahme löschen BASS_StreamFree(chan); WaveStream.Clear; end; // if end else if InsertRadioButton.Checked = True then begin WaveStream.Position := ProgressBar.Position; end else if EndRadioButton.Checked = True then begin WaveStream.Position := WaveStream.Size; ProgressBar.Position := ProgressBar.Max; end; // if // Header für WAV-File generieren with WaveHdr do begin riff := 'RIFF'; len := 36; cWavFmt := 'WAVEfmt '; dwHdrLen := 16; wFormat := 1; wNumChannels := 2; dwSampleRate := 44100; wBlockAlign := 4; dwBytesPerSec := 176400; wBitsPerSample := 16; cData := 'data'; dwDataLen := 0; end; // with WaveStream.Write(WaveHdr, SizeOf(WAVHDR)); i := 0; vol := RecordPegelBar.Position/100; while BASS_RecordSetInput(i, BASS_INPUT_OFF, vol) do i := i + 1; // ---LoWord-- ----HiWord---- Flag := MakeLong(c16BitAudio, cRecordingTime); // Aufnahmebeginn @ 44100hz 16-bit stereo rchan := BASS_RecordStart(cSamplerate, cNumChannels, Flag, @RecordingCallback, nil); if rchan = 0 then begin MessageDlg('Aufnahme konnte nicht gestartet werden!', mtError, [mbOk], 0); WaveStream.Clear; end; end; // procedure StartRecording (* Stop recording *) procedure TRecordForm.StopRecording; var i: integer; begin BASS_ChannelStop(rchan); // WAV-Header komplettieren WaveStream.Position := 4; i := WaveStream.Size - 8; WaveStream.Write(i, 4); i := i - $24; WaveStream.Position := 40; WaveStream.Write(i, 4); WaveStream.Position := 0; // Stream für aufgenomme Daten kreieren chan := BASS_StreamCreateFile(True, WaveStream.Memory, 0, WaveStream.Size, 0); if chan <> 0 then begin ProgressBar.Max := WaveStream.Size; BASS_ChannelSetPosition(chan, ProgressBar.Max, BASS_POS_BYTE); ProgressBar.Position := BASS_ChannelGetPosition(chan, BASS_POS_BYTE); end else begin MessageDlg('Fehler beim Erstellen eines Streams aus der Aufnahme!', mtError, [mbOk], 0); end; // if end; // procedure StopRecording (* RecordButtonClick || Start Aufnahme *) procedure TRecordForm.RecExecute(Sender: TObject); begin if BASS_ChannelIsActive(rchan) = BASS_Active_Stopped then // Aufnahme starten begin if BASS_ChannelIsActive(chan) <> BASS_Active_Stopped then begin BASS_ChannelStop(chan); ProgressBar.Position := ProgressBar.Max; StartRecording; end else begin ProgressBar.Position := ProgressBar.Max; StartRecording; end; // if ToggleStatus(8); end else if BASS_ChannelIsActive(rchan) = BASS_Active_Playing then // Aufnahme beenden begin StopRecording; ToggleStatus(3); end; end; //procedure RecExecute (* StopButtonClick || Stop Aufnahme *) procedure TRecordForm.StopExecute(Sender: TObject); begin case BASS_ChannelIsActive(chan) of BASS_Active_Stopped: begin BASS_ChannelSetPosition(chan, 0, BASS_POS_BYTE); ProgressBar.Position := BASS_ChannelGetPosition(chan, BASS_POS_BYTE); ToggleStatus(3); end; // case BASS_Active_Stopped BASS_Active_Playing: begin BASS_ChannelStop(chan); BASS_ChannelSetPosition(chan, 0, BASS_POS_BYTE); ProgressBar.Position := BASS_ChannelGetPosition(chan, BASS_POS_BYTE); ToggleStatus(3); end; // case BASS_Active_Playing BASS_Active_Paused: begin BASS_ChannelStop(chan); BASS_ChannelSetPosition(chan, 0, BASS_POS_BYTE); ProgressBar.Position := BASS_ChannelGetPosition(chan, BASS_POS_BYTE); ToggleStatus(3); end; // case BASS_Active_Paused end; //case end; // procedure StopExecute |
Re: Ende von Aufnahme erkennen 'bass.dll'
Machs mal so!
Delphi-Quellcode:
const
um_MusicEnd = wm_User + 400;
Delphi-Quellcode:
TfrmMain = class(TForm)
private EndSync : HSync; protected procedure MusicEnd(var Msg: TMessage); message um_MusicEnd; public // .. end;
Delphi-Quellcode:
procedure SyncProc(Handle: HSync; Channel, Data: DWORD; User: DWORD); stdcall;
begin PostMessage(frmMain.Handle, um_MusicEnd, 0, 0); end;
Delphi-Quellcode:
gruss Emil
procedure TfrmMain.MusicEnd(var Msg: TMessage);
begin // hier wird reingesprungen wenn der Stream endet // der mit .. EndSync := Bass_ChannelSetSync(Stream, Bass_SYNC_END, 0, @SyncProc, nil); // vorher in deiner Play Function initialisiert wurde (**** nicht hier ****) // hier sollte dann dein Code stehen was du tun willst wenn der stream beendet ist. end; |
Re: Ende von Aufnahme erkennen 'bass.dll'
Danke für die schnelle Antwort. :)
Delphi-Quellcode:
So sieht das jetzt bei mir aus, allerdings kommt beim Compilieren die Fehlermeldung, dass eine Variable erforderlich ist und der Debugger springt auf folgende Zeile:
(* PlayButtonClick || Wiedergabe der Aufnahme *)
procedure TRecordForm.PlayExecute(Sender: TObject); var EndSync: HSYNC; begin case BASS_ChannelIsActive(chan) of BASS_Active_Stopped: begin BASS_ChannelPlay(chan, True); EndSync := Bass_ChannelSetSync(chan, Bass_SYNC_END, 0, @SyncProc, nil); ToggleStatus(1); end; BASS_Active_Playing: begin BASS_ChannelPause(chan); ToggleStatus(2); end; BASS_Active_Paused: begin BASS_ChannelPlay(chan, False); ToggleStatus(1); end; end; // case end; // procedure PlayExecute procedure SyncProc(Handle: HSync; Channel, Data: DWORD; User: DWORD); stdcall; begin PostMessage(RecordForm.Handle, um_MusicEnd, 0, 0); end; procedure TRecordForm.MusicEnd(var Msg: TMessage); begin // hier wird reingesprungen wenn der Stream endet // der mit .. MessageDlg('Dies ist ein Test.'); // vorher in deiner Play Function initialisiert wurde (**** nicht hier ****) // hier sollte dann dein Code stehen was du tun willst wenn der stream beendet ist. end; EndSync := Bass_ChannelSetSync(chan, Bass_SYNC_END, 0, @SyncProc, nil); Hab ich da was verkehrt gemacht? |
Re: Ende von Aufnahme erkennen 'bass.dll'
Delphi-Quellcode:
EndSync:DWord;
|
Re: Ende von Aufnahme erkennen 'bass.dll'
Also
Delphi-Quellcode:
sollte besser unter Privat in class(TForm) stehen oder ?
EndSync : HSync;
Delphi-Quellcode:
TfrmMain = class(TForm)
private EndSync : HSync; protected procedure MusicEnd(var Msg: TMessage); message um_MusicEnd; public // .. end;
Delphi-Quellcode:
Müßte eigentlich in der Bass.pas stehen.
HSYNC = DWORD; // synchronizer handle
Andernfalls definiere es wie @Blackheart geschrieben hat. gruss Emil |
Re: Ende von Aufnahme erkennen 'bass.dll'
Delphi-Quellcode:
So sehen jetz meine Deklarationen aus. Ich habe sowohl Endsync als sync, sowie als dword versucht zu deklarieren. Der Fehler bleibt bestehen. Kann es sein, dass ich einen Fehler in der SyncProc habe? Der Cursor bleibt nämlich immer bei @SyncProc stehen.
type
TRecordForm = class(TForm) RecordControlBar: TControlBar; RecordMainMenu: TActionMainMenuBar; ListPnl: TPanel; RecordSplitter: TSplitter; RecorderPnl: TPanel; RecordTimer: TTimer; RecActionList: TActionList; Rec: TAction; Stop: TAction; Play: TAction; Start: TAction; Previous: TAction; Next: TAction; Ende: TAction; DiktatListView2: TShellListView; ToolActionManager: TActionManager; ActionToolBar1: TActionToolBar; RecImageList: TImageList; Save: TAction; RecSaveDialog: TSaveDialog; Open: TAction; OpenDialog1: TOpenDialog; RecImageList2: TImageList; MenuActionManager: TActionManager; VisualTimer: TTimer; RecGroupBox: TGroupBox; AufnahmeRadioGroup: TRadioGroup; EndRadioButton: TRadioButton; InsertRadioButton: TRadioButton; OverWriteRadioButton: TRadioButton; SettingsGroupBox: TGroupBox; InputLbl: TLabel; VolumeLbl: TLabel; VolumePegelBar: TTrackBar; RecordPegelBar: TTrackBar; VisPanel: TPanel; ProgressBar: TTrackBar; VisPaintBox: TPaintBox; SaveSend: TAction; SendAs: TAction; ShellPUM: TPopupMenu; DictSendAs: TMenuItem; DeletePrev: TAction; DeleteFollowing: TAction; InsPassage: TAction; procedure FormActivate(Sender: TObject); procedure SaveSendExecute(Sender: TObject); procedure SendAsExecute(Sender: TObject); procedure DiktatListView2DblClick(Sender: TObject); procedure VisualTimerTimer(Sender: TObject); procedure OpenExecute(Sender: TObject); procedure SaveExecute(Sender: TObject); procedure EndeExecute(Sender: TObject); procedure StartExecute(Sender: TObject); procedure PlayExecute(Sender: TObject); procedure StopExecute(Sender: TObject); procedure RecExecute(Sender: TObject); procedure ProgressBarChange(Sender: TObject); procedure VolumePegelBarChange(Sender: TObject); procedure RecordPegelBarChange(Sender: TObject); procedure RecordTimerTimer(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure StartRecording; procedure StopRecording; procedure SyncProc(Handle: HSync; Channel, Data: DWORD; User: DWORD); stdcall; const um_MusicEnd = wm_User + 400; private EndSync: DWord; WaveStream: TMemoryStream; BufStream: TMemoryStream; ChannelVol: Integer; procedure ToggleStatus(const Status: Integer); procedure ReadConfig; protected procedure MusicEnd(var Msg: TMessage); message um_MusicEnd; public FRecordingsPath, User: string; AnhangDir: String; end; var RecordForm: TRecordForm; WaveHdr: WAVHDR; // WAV header rchan: HRECORD; // Aufnahmekanal chan: HSTREAM; // Wiedergabekanal mic: integer; volume: Float; input: Float; Ich habe jetzt auch die Doku der bass.dll durchgeschaut aber der zufolge müsste alles richtig sein. MfG |
Re: Ende von Aufnahme erkennen 'bass.dll'
Zitat:
Fällt dir was auf ?
Delphi-Quellcode:
private
EndSync: DWord;
Delphi-Quellcode:
Wenn HSync in de BASS.pas nicht enthalten ist
procedure SyncProc(Handle: HSync; Channel, Data: DWORD; User: DWORD); stdcall;
was muss man dann machen ? gruss Emil |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:49 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz