| Autor |
Beitrag |
F34r0fTh3D4rk
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Mo 21.01.08 20:07
Hi,
Ich suche eine Möglichkeit, zwei Wave Dateien direkt hintereinander zu schneiden und als eine Wave abzuspeichern,
wie stelle ich das am besten an ? ("Mit Bass.dll" oder "Mit FMOD" reicht mir als Antwort leider nicht  )
mfg
|
|
Sinspin
      
Beiträge: 1340
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Mo 21.01.08 21:49
Mit Mono Dateien habe ich das schonmal bei meinem DOS Synthesizer gemacht. Ich habe mir auch eine Procedure geschrieben die an den fügestellen das Knacken entfernt was entstehen kann wenn die Amplitude des Endsamples und des neuen Startsamples zuweit auseinander liegt.
Für Stereo müsste man das ja eigentlich genauso hinbekommen.
Die Frage ist nur ob es heutzutage nicht fertige Tools gibt die das besser hinbekommen.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Di 22.01.08 15:17
Ja ich benötige das allerdings in einem anderen Kontext. Welche Möglichkeiten habe ich ? Ich muss die beiden nur direkt hintereinander schneiden, nicht bearbeiten oder so.
mfg
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 23.01.08 13:04
Lese WAV-Spec, sehe, dass das n Container-Format ist, überprüfe, dass die Format-Spec identisch ist (Sollte herfür eines der PCM-Formate sein).
Öffne nun die erste Datei, addiere zu Offset 4 die Größe des Datecontainers des zweiten Files. Passe die Container-Größe des ersten Files um diese Größe an, hänge den Inhalt des Datencontainers aus der zweiten File ans Ende der ersten Datei an ...
Mit Hilfe der OVFS-Stream IIRC ne Sache von 40 Zeilen ... (in Zwanzi Zeilen bekommt man do mit voller Fehlerprüfung das Auslesen der Spielzeit hin ...)
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Mi 23.01.08 19:49
Ich habs jetzt mal "per Hand" versucht. Allerdings habe ich das Problem, dass ich den Inhalt des Data Chunks nicht auslesen kann. Ich habe alles Mögliche versucht, allerdings sind meine Daten immer leer.
Hier mal mein Code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| const cRIFF = 'RIFF'; cWAVE = 'WAVE'; cfmt = 'fmt '; cdata = 'data'; |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| type TRIFFHeader = record filesize: cardinal; end; TfmtHeader = record samplerate, bytessecond: cardinal; formattag, channels, blockalign, bitssample: smallint; end; TdataHeader = record datasize: cardinal; wdata: array of byte; end; |
Dieser Code hier stammt aus dem Easy Delphi Helper:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| function GotoChunk(pStream: TFilestream; ID: string): Integer; var chunkID: array[0..3] of char; chunkSize: Integer; begin Result := -1; with pStream do begin Position := 12; repeat Read(chunkID, 4); Read(chunkSize, 4); if chunkID <> ID then Position := Position + chunkSize; until (chunkID = ID) or (Position >= Size); if chunkID = ID then Result := chunkSize; end end; |
Dieser hier nicht mehr:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
| function ReadWave(filename: string; var riff: TRIFFheader; var fmt: Tfmtheader; var data: Tdataheader): boolean; var Stream: TFileStream; hRIFF, hWAVE: array[0..3] of char; begin result := false; Stream := TFilestream.Create(filename, fmOpenRead or fmShareDenyWrite); with Stream do try Read(hriff, 4); Read(riff.filesize, 4); Read(hWAVE, 4); if (hRIFF = cRIFF) and (hWAVE = cWAVE) then begin if (GotoChunk(Stream, cfmt) <> -1) then begin Read(fmt.formattag, 2); Read(fmt.channels, 2); Read(fmt.samplerate, 4); Read(fmt.bytessecond, 4); Read(fmt.blockalign, 2); Read(fmt.bitssample, 2); data.datasize := GotoChunk(Stream, cdata); if data.datasize > 0 then begin setlength(data.wdata, data.datasize); read(data.wdata, data.datasize); result := true; end; end; end; finally Free; end; end; |
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| var Stream: TFileStream; nfilesize: cardinal; fmtsize: integer; begin Stream := TFilestream.Create(filename, fmCreate); with Stream do try Write(cRIFF, 4); nfilesize := data.datasize + 36; Write(nfilesize, 4); Write(cWAVE, 4); Write(cfmt, 4); fmtsize := 16; Write(fmtsize, 4); Write(fmt.formattag, 2); Write(fmt.channels, 2); Write(fmt.samplerate, 4); Write(fmt.bytessecond, 4); Write(fmt.blockalign, 2); Write(fmt.bitssample, 2); Write(cdata, 4); Write(data.datasize, 4); Write(data.wdata, data.datasize); finally Free; end; end; |
Es lässt sich alles wunderbar auslesen und schreiben und ist data.wdata leer, warum ?
mfg
Zuletzt bearbeitet von F34r0fTh3D4rk am Do 24.01.08 17:14, insgesamt 2-mal bearbeitet
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 23.01.08 20:41
Wenn du das mit dem Header gelöst hast kommt noch eine weitere Schwierigkeit hinzu:
Die Datenpakete einfach zusammenstecken erzeugt mit hoher Wahrscheinlichkeit ein kurzes Klickgeräusch, da die Waveform beim Schnitt mit hoher Wahrscheinlichkeit nicht stetig ist. Du musst die Waveform in der Nähe des Schnitts so zusammenbiegen, dass sie stetig wird - oder beide in der Nähe des Schnitts zu 0 biegen, ansonsten erzeugst du eine Schockwelle 
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Mi 23.01.08 21:13
Ich habe mir die Dateien gerade mal angeguckt, sie enden nicht komplett lautlos (aber schon nicht mehr wirklich hörbar), ist das schlimm ? (Mit audacity aneinanderhängen macht auf jeden Fall keine Probleme, aber das ist auch was anderes)
Für Lösungsvorschläge / Alternativen bin ich offen
(vor allem zu dem Problem, dass ich die Wave Daten nicht ausgelesen bekomme  )
mfg
|
|
Sinspin
      
Beiträge: 1340
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Do 24.01.08 11:51
Eine Webseite auf der sich was zum Lesen und Schreiben von Wavedateien finden lassen dürfte : www.wotsit.org/
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 24.01.08 15:21
Ich hab die Doku doch schon, ich habe soweit auch alles auslesen können. Der Code müsste eigentlich schon funktionieren,
allerdings funktioniert das mit den wave daten nicht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| data.datasize := GotoChunk(Stream, cdata); if data.datasize > 0 then begin setlength(data.wdata, data.datasize); read(data.wdata, data.datasize); result := true; end; |
vielleicht liegt das problem bei meinem datentyp, aber ich habe schon alles mögliche probiert.
Wenn ich an diese stelle ein ReadBuffer setze, bekommt ich einen Stream Read Error.
mfg
Zuletzt bearbeitet von F34r0fTh3D4rk am Do 24.01.08 17:13, insgesamt 1-mal bearbeitet
|
|
Sinspin
      
Beiträge: 1340
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Do 24.01.08 17:02
F34r0fTh3D4rk hat folgendes geschrieben: |
vielleicht liegt das problem bei meinem datentyp, aber ich habe schon alles mögliche probiert.
|
Damit hast du recht, alle deine Records müssen aus jeden Fall packed sein.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| type TRIFFHeader = packed record filesize: cardinal; end; TfmtHeader = packed record samplerate, bytessecond: cardinal; formattag, channels, blockalign, bitssample: smallint; end; TdataHeader = packed record datasize: cardinal; wdata: array of byte; end; |
Ansonsten hast du eine 4 oder 8-Byte Datenausrichtung und damit liest man eigentlich immer nur Müll.
Mit Vorsicht ist auch die datasize zu genießen, die wirkliche Größe der Daten ergibt sich aus der Anzahl der Samples, der Channels und der Bitbreite.
Zudem wird Normalerweise immer aus ganze Word (16-Bit) "aufgerundet" (wenn ich mich recht erinnere)
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 24.01.08 17:11
An dem packed hats nicht gelegen (kann ich mir eigentlich auch nicht vorstellen). Und die Größe die ich bekomme, sollte eigentlich stimmen. Woher bekomme ich denn die Anzahl der Samples ? (Es funktioniert übrigens auch nicht z.B. 4 bytes zu lesen, das aber nur an der einen stelle)
mfg
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Do 24.01.08 17:59
F34r0fTh3D4rk hat folgendes geschrieben: | Ich hab die Doku doch schon, ich habe soweit auch alles auslesen können. Der Code müsste eigentlich schon funktionieren,
allerdings funktioniert das mit den wave daten nicht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| data.datasize := GotoChunk(Stream, cdata); if data.datasize > 0 then begin setlength(data.wdata, data.datasize); read(data.wdata, data.datasize); result := true; end; |
vielleicht liegt das problem bei meinem datentyp, aber ich habe schon alles mögliche probiert.
Wenn ich an diese stelle ein ReadBuffer setze, bekommt ich einen Stream Read Error.
mfg |
data.wdata ist ein dynamisches Array, data.wdata ist also nur ein Pointer. Du musst wenn schon nach data.wdata[0] schreiben, oder wie in älteren Codes wdata als statisches à la array[0..0] oder [0..$FFFFFxxx] definieren, allenfalls die Range-Checks ausschalten und den notwendigen Speicher selbst mit GetMem allozieren und mit Pointern arbeiten. Ich empfehle ersteres.
Zuletzt bearbeitet von delfiphan am Do 24.01.08 18:06, insgesamt 2-mal bearbeitet
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Do 24.01.08 18:02
sowas hab ich mir schon gedacht, danke jetzt gehts
Das verketten zweier / mehrerer Wave funktioniert ebenfalls.
Hier der Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| function MergeMultipleWaves(inputs: TStringArray; output: string): boolean; function CompareFMT(fmt1, fmt2: Tfmtheader): boolean; begin result := (fmt1.samplerate = fmt2.samplerate) and (fmt1.bytessecond = fmt2.bytessecond) and (fmt1.channels = fmt2.channels) and (fmt1.formattag = fmt2.formattag) and (fmt1.blockalign = fmt2.blockalign) and (fmt1.bitssample = fmt2.bitssample); end; var riff: TRiffheader; fmt: Tfmtheader; data: Tdataheader; ergriff: TRiffheader; ergfmt: Tfmtheader; ergdata: TDataheader; i, d, oldsize: integer; begin result := false; for i := 0 to high(inputs) do begin if ReadWave(inputs[i], riff, fmt, data) then if (i = 0) then begin ergriff.filesize := riff.filesize; ergfmt := fmt; ergdata.datasize := 0; end else if CompareFMT(fmt, ergfmt) then ergriff.filesize := ergriff.filesize + data.datasize else exit; oldsize := ergdata.datasize; ergdata.datasize := ergdata.datasize + data.datasize; setlength(ergdata.wdata, ergdata.datasize); for d := 0 to data.datasize - 1 do ergdata.wdata[d + oldsize] := data.wdata[d]; end; WriteWave(output, ergriff, ergfmt, ergdata); result := true; end; |
mfg
|
|
|