![]() |
Stille aus Wave-Dateien entfernen?
Hallo Zusammen,
ich bräuchte mal ein paar Tips wie ich es anstellen kann, eine Wave-Datei zu trimmen, will heißen, stille, am Anfang und Ende einer Wave-Datei rauszuschneiden. Das muß nicht supergenau sein, mir geht es um folgendes: Mein Benutzer drückt den Startknopf, sabbelt was ins Mikrophon, rappelt noch ein wenig, und drückt dann stopp. Das ergebnis soll eine Wave mit möglichst nur seinem gesabbel werden. Meine Fragen: Wie kann ich den Anfang bzw. das Ende einer Wave abschneiden? (gern mit BASS) Wie kriege ich raus, ab wo das "gesabbel" anfängt und wo es aufhört? Mit der Lautsträrke, klar, aber ich find die Funktion ums verrecken nicht. *grummel! Für Tips wäre ich sehr dankbar! Einen freundlichen Gru´ß Marco |
Re: Stille aus Wave-Dateien entfernen?
stille ist eigentlich nur ein geringer Ausschlag. Du müsstest also nur alles Samples vom Anfang an durchgehen und schauen ab wann ein Sample den von dir definierten Minimalausschlag überschreitet.
Ich würde dazu einfach die Datei mit einem TStream (TFileStream) öffnen und dann entsprechend dem Header bis zu den WaveDaten navigieren. Dort Sample für Sample lesen und schauen wie groß der Ausschlag ist. |
Re: Stille aus Wave-Dateien entfernen?
Zitat:
Dazu bräuchte ich bitte nochmal einen tip! Viele Grüße Marco |
Re: Stille aus Wave-Dateien entfernen?
Du könntest eine FFT machen (mit BASS, Beispiele dazu gibts ja hundertfach hier im Forum) und dann den Ausschlag in verschiedenen Frequenzen Sample für Sample messen, bis eben eine Grenze überschritten wird. Dabei kannst du ja verwenden, dass gesprochene Sprache meist andere Frequenzen nutzt, als Umgebungsgeräusche oder das "rumgerappeln". Kannst du ja dann testen und entsprechend gewichten :)
|
Re: Stille aus Wave-Dateien entfernen?
Hi
Delphi-Quellcode:
function Channel_Get_SilenceLength_16Bit(FileName : String; Pinpoint : Boolean; Threshold : QWORD; var StartPoint, EndPoint : DWORD) : Bool; stdcall;
var a, b: Integer; pos, count, chan: DWORD; buf16: array[0..50000] of Smallint; // 100% OK. flag : DWORD; begin result:= false; count := 0; flag:= BASS_STREAM_DECODE; //BASS_STREAM_DECODE or BASS_STREAM_AUTOFREE if Pinpoint then flag:= flag or BASS_STREAM_PRESCAN; Chan:= BASS_StreamCreateFile(FALSE, PChar(FileName), 0, 0, Flag); if Chan = 0 then Chan:= BASS_MusicLoad(False, PChar(FileName), 0, 0, Flag or BASS_MUSIC_NOSAMPLE, 0); if Chan = 0 then Exit; while Bass_ChannelIsActive(Chan) <> 0 do begin b := BASS_ChannelGetData(Chan, @buf16, 20000); b := b div 2; a := 0; while (a < b) and (Abs(buf16[a]) <= Threshold) do a := a + 1; count := count + (a * 2); if (a < b) then begin while (a <> 0) and (Abs(buf16[a]) > (Threshold div 4)) do begin a := a - 1; count := count - 2; end; Break; end; end; StartPoint := count; // Start-Point ready pos := BASS_ChannelGetLength(Chan); while (pos > count) do begin if pos < 100000 then pos := 0 else pos := pos - 100000; BASS_ChannelSetPosition(chan, pos); b := BASS_ChannelGetData(chan, @buf16, 100000); b := b div 2; a := b; while (a > 0) and (Abs(buf16[a - 1]) <= (Threshold div 2)) do a := a - 1; if a > 0 then begin count := pos + (a * 4); Break; end; end; EndPoint := Count; // End-Point ready BASS_MusicFree(Chan); BASS_StreamFree(Chan); Result:= true; end; function Channel_Get_SilenceLength_32Bit(FileName : String; Pinpoint : Boolean; Threshold : QWORD; var StartPoint, EndPoint : DWORD) : boolean; stdcall; var a, b: Integer; pos, count, chan: DWORD; buf32: array[0..50000] of Float; //Single flag : DWORD; begin Result:= false; Flag:= BASS_STREAM_DECODE or BASS_SAMPLE_FLOAT; if Pinpoint then Flag:= Flag or BASS_STREAM_PRESCAN; Chan:= (BASS_StreamCreateFile(FALSE, PChar(FileName), 0, 0, Flag)); if Chan = 0 then Chan:= BASS_MusicLoad(False, PChar(FileName), 0, 0, Flag or BASS_MUSIC_NOSAMPLE, 0); if Chan = 0 then Exit; count := 0; while Bass_ChannelIsActive(chan) <> 0 do begin b := BASS_ChannelGetData(chan, @buf32, 20000); b := b div 4; a := 0; while (a < b) and (Abs(buf32[a]) <= (Threshold / 32768)) do a := a + 1; count := count + (a * 4); if (a < b) then begin while (a <> 0) and (Abs(buf32[a]) > (Trunc(Threshold / 32768) div 4)) do begin a := a - 1; count := count - 2; end; Break; end; end; StartPoint := count; // Start-Point ready pos := BASS_ChannelGetLength(chan); while (pos > count) do begin if pos < 100000 then pos := 0 else pos := pos - 100000; BASS_ChannelSetPosition(chan, pos); b := BASS_ChannelGetData(chan, @buf32, 100000); b := b div 4; // 16Bit = 2 | 32Bit = 4 a := b; while (a > 0) and (Abs(buf32[a - 1]) <= (Threshold div 2) / 32768) do a := a -1; if a > 0 then begin count := pos + (a * 8); //8=2 Break; end; end; EndPoint := Count; // End-Point ready BASS_MusicFree(Chan); BASS_StreamFree(chan); Result:= true; end; |
Re: Stille aus Wave-Dateien entfernen?
Hi Wishmaster,
Ganz herzlichen Dank für den Quellcode. Mein Ansatz war, die Werte mittels BASS_ChannelGetLevel rauszufinden. Allerdings bin ich nicht auf die Idee gekommen, das ganze, für das Ende, rückwärts anzugehen, ich hab einfach mehrere Levels verglichen, und wenn’s 20 mal unterm threshold war, dann war schluß. ;-) Da ist deines natürlich um Längen besser. Ich habe noch ein paar Fragen zum Code: 1. Wofür ist die möglichkeit des PreScan hier sinnvoll? 2. Warum vergleichst du auf Threshold div 2 bzw. threshold div 4? Die Fragen, weil ich gerne verstehen würde, wie du es gemacht hast. So, und damit man das Resultat auch als Wave-Datei hat, ;-), hier der Rest des Programms. Kann man das evtl. noch verbessern?
Delphi-Quellcode:
Ich hab’s auch schon mittels eine BASS_SYNC_Pos probiert, aber der Sync wird niemals erreicht.
procedure TMainForm.BStartClick(Sender: TObject);
const Buffersize = 1024; var sh: HSTREAM; // sound handle eh: HENCODE; // encoder handle buf: array of byte; Startposition, Endposition: dWord; begin SetLength (buf, BufferSize); BASS_init (-1, 44100, 0, application.handle, nil); if not Channel_Get_SilenceLength_16Bit ('Test.wav', true, 5000, Startposition, Endposition) then begin ErrorMsg ('Calculation of silence failed!'); exit end; sh := BASS_StreamCreateFile (false, pChar('test.wav'), 0, 0, BASS_Stream_Decode); if sh = 0 then begin ErrorMsg ('Could not open input file.'); exit end; BASS_ChannelSetPosition (sh, Startposition, BASS_POS_Byte); eh := BASS_Encode_Start (sh, pChar('test_silent.wav'), BASS_Encode_PCM + BASS_Encode_AutoFree, nil, nil); if eh = 0 then begin ErrorMsg ('Encoder not started.'); BASS_StreamFree (sh); exit end; While BASS_ChannelIsActive (sh) <> BASS_ACTIVE_Stopped do begin BASS_ChannelGetData (sh, buf, Buffersize); if BASS_ChannelGetPosition (sh, BASS_Pos_Byte) >= EndPosition then BASS_ChannelStop (sh); end; BASS_StreamFree (sh); Infobox ('Ready!'); end; Freundliche Grüße Marco |
Re: Stille aus Wave-Dateien entfernen?
Hi
ich freue mich das dir der code weiter geholfen hat. PreScan ist mehr für MP3s gedacht. Benutze es nur wen du das unbedingt brauchst, es dauert en Stück länger um eine mp3 Datei zu Laden. Aus der bass Hilfe Zitat:
1, wen möglich verwende immer 32 Bit (bessere qualität) 2, ich würde an deiner stelle die bassmix.dll benutzen in deinem Code würde ich den buffer vergrößern besonders wen du nach wma encodieren willst
Delphi-Quellcode:
var Buff32 : Array [0..20000] of FLOAT; // 32 Bit
BASS_ChannelGetData(Channel, @Buff32, SizeOf(Buff32)); var Buff16 : Array [0..20000] of LongInt; // 16 Bit Result:=BASS_ChannelGetData(Channel, @Buff16, SizeOf(Buff16)); |
Re: Stille aus Wave-Dateien entfernen?
Hallo Wishmaster,
Zitat:
Zitat:
Zitat:
Viele Grüße Marco |
Re: Stille aus Wave-Dateien entfernen?
Hi
Zitat:
du kannst auch die Lautstärke und Balance ändern Zitat:
Zitat:
Delphi-Quellcode:
Procedure Encode(inFile, outFile : String; Samplerate, Bits, Channels : integer) // 44100, 16, 2
Var Channel, Mixer : DWORD; Flag, encFlag : DWORD; StopTime : INT64; begin Channel:= BASS_StreamCreateFile(FALSE, PChar(inFile), 0, 0, Flag); Mixer := BASS_Mixer_StreamCreate(Samplerate, Channels, BASS_SAMPLE_FLOAT or BASS_STREAM_DECODE); (* limiting the duration to X seconds StopTime = The maximum amount of data (in bytes) to mix... 0 = no limit. *) StopTime := BASS_ChannelSeconds2Bytes(Mixer, 2) ; // in Sec. Flag:= BASS_MIXER_LIMIT or BASS_MIXER_FILTER or BASS_MIXER_BUFFER; BASS_Mixer_StreamAddChannelEx(Mixer, Channel, Flag, 0, StopTime); BASS_ChannelSetPosition (..., Startposition, BASS_POS_Byte); encFlag:= 0; if Bits = 8 then encFlag:= encFlag or BASS_ENCODE_FP_8BIT; if Bits = 16 then encFlag:= encFlag or BASS_ENCODE_FP_16BIT; if Bits = 24 then encFlag:= encFlag or BASS_ENCODE_FP_24BIT; if Bits = 32 then encFlag:= encFlag or BASS_ENCODE_FP_32BIT; // else 32 Bit (floating-point) BASS_Encode_Start(..., PChar(outFile), encFlag or BASS_Encode_AutoFree, nil, nil) |
Re: Stille aus Wave-Dateien entfernen?
Hallo,
Ich hab mir den Code heute nochmal zu gemüte geführt und, denke?, er hat einen Fehler.
Delphi-Quellcode:
Das gleiche gilt, natürlich, auch für die 32-Bit-Variante.
function Channel_Get_SilenceLength_16Bit(FileName : String; Pinpoint : Boolean; Threshold : QWORD; var StartPoint, EndPoint : DWORD) : Bool; stdcall;
var a, b: Integer; pos, count, chan: DWORD; buf16: array[0..50000] of Smallint; // 100% OK. flag : DWORD; begin result:= false; count := 0; flag:= BASS_STREAM_DECODE; //BASS_STREAM_DECODE or BASS_STREAM_AUTOFREE if Pinpoint then flag:= flag or BASS_STREAM_PRESCAN; Chan:= BASS_StreamCreateFile(FALSE, PChar(FileName), 0, 0, Flag); if Chan = 0 then Chan:= BASS_MusicLoad(False, PChar(FileName), 0, 0, Flag or BASS_MUSIC_NOSAMPLE, 0); if Chan = 0 then Exit; while Bass_ChannelIsActive(Chan) <> 0 do begin b := BASS_ChannelGetData(Chan, @buf16, 20000); b := b div 2; a := 0; while (a < b) and (Abs(buf16[a]) <= Threshold) do a := a + 1; count := count + (a * 2); if (a < b) then begin while (a <> 0) and (Abs(buf16[a]) > (Threshold div 4)) do begin a := a - 1; count := count - 2; end; Break; end; end; StartPoint := count; // Start-Point ready pos := BASS_ChannelGetLength(Chan); while (pos > count) do begin if pos < 100000 then pos := 0 else pos := pos - 100000; BASS_ChannelSetPosition(chan, pos); b := BASS_ChannelGetData(chan, @buf16, 100000); // ... so, hier geht's los: b := b div 2; // b ist also die Anzahl der samples a := b; while (a > 0) and (Abs(buf16[a - 1]) <= (Threshold div 2)) do a := a - 1; if a > 0 then begin count := pos + (a * 4); // warum 4, müßte doch bei smallint, also 2 byte, * 2 heißen, oder? Break; end; end; EndPoint := Count; // End-Point ready BASS_MusicFree(Chan); BASS_StreamFree(Chan); Result:= true; end; Der Code produziert nämlich manchmal Ergebnisse, deren Endposition größer ist, als die tatsächliche Länge. Hilf mir mal bitte! Einen freundlichen Gruß Marco |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:14 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