Die Klasse TWaveProvider liest auch die eigentlichen Audiodaten ein, und packt sie in je ein Array pro Kanal (Links/Rechts). Anhand der Samplerate (TWaveProvider.Samplerate) kannst du nun errechnen, wie viele Werte du von den Arrays vorn wegschneiden musst, um auf vier Sekunden zu kommen. 44.1kHz Samplerate hast du also 44100 Werte pro Sekunde.
Ich habe hier auch noch Code rumliegen, der eine valide Wave Datei schreiben kann, was du ja denke ich auch machen müsstest.
Delphi-Quellcode:
TRIFFHeader = packed record
id : array[0..3] of Char;
length: DWORD;
waveId: array[0..3] of Char;
end;
TWaveFormatChunk = packed record
id : array[0..3] of Char;
length : DWORD;
FormatTag : WORD; // Format category
Channels : WORD; // Number of channels
SamplesPerSec : DWORD; // Sampling rate
AvgBytesPerSec: DWORD; // For buffer estimation
BlockAlign : WORD; // Data block size
BitsPerSample : WORD;
end;
TDataHeader = packed record
id : array[0..3] of Char;
length: DWORD;
end;
implementation
procedure TForm1.SaveWave(FileName: String);
var
Header : TRIFFHeader;
Fmt : TWaveFormatChunk;
Data : TDataHeader;
WaveOut : TFileStream;
WaveLength: Integer;
DeinArrayMitWavedaten: array of SmallInt;
begin
WaveOut := TFileStream.Create(FileName, fmCreate);
WaveLength := Length(DeinArrayMitWavedaten);
Header.id := 'RIFF';
Header.length := 4 {Length(Header.waveId)} + WaveLength + SizeOf(TWaveFormatChunk)+ SizeOf(TDataHeader);
Header.waveId := 'WAVE';
Fmt.id := 'fmt ';
Fmt.length := SizeOf(TWaveFormatChunk)-8;
Fmt.FormatTag := $0001; // WAVE_FORMAT_PCM
Fmt.Channels := 2;
Fmt.SamplesPerSec := 44100;
Fmt.AvgBytesPerSec:= 176400; // Samplerate*Channels*(BitsPerSample/8)
Fmt.BlockAlign := 4;
Fmt.BitsPerSample := 16;
Data.id := 'data';
Data.length := WaveLength;
WaveOut.Write(Header, SizeOf(TRIFFHeader));
WaveOut.Write(Fmt, SizeOf(TWaveFormatChunk));
WaveOut.Write(Data, SizeOf(TDataHeader));
WaveOut.Write(DeinArrayMitWavedaten, WaveLength);
WaveOut.Free;
end;
Das habe ich fix aus einem anderen Projekt zusammen kopiert, in dem die einzelnen Schritte etwas verteilter durchgeführt wurden. Ich hoffe, dass das funktionieren kann - zumindest aber sollte es das Prinzip zeigen
. Mit etwas Schreiberei ließe sich das Speichern auch in TWaveProvider einbauen, ich hab das nur nicht getan, da ich bislang kein Bedarf dafür hatte.
Die Funktion oben schreibt nun immer ein 16 Bit Stereo Wave mit 44.1kHz Samplerate (CD-Standard). Worauf du bei Stereo unbedingt achten musst: Die Sampledaten für linken und rechten Kanal müssen abwechselnd geschrieben werden, beginnend mit dem linken. Das ist nun leider insofern etwas dumm, als dass TWaveProvider 2 Arrays mit den aufgetrennten Kanälen lieftert. Diese müsste man also zunächst wieder miteinander verschränken
.
Was hinten raus kommen sollte, ist ein handelsübliches Wave File, dass eigntlich alle Programme die Waves lesen können, verarbeiten können sollte, da hier nur die einfachste und ursprüngliche Form eines Waves geschrieben wird, ohne großen Schnickschnack. (RIFF-Wave ist, wie auch AVI z.B. ein Containerformat, mit dem man allerhand Zeug anstellen könnte. So gibts z.B. auch die Möglichkeit mp3 in Wave zu verpacken, oder programmspezifische Informationen. Nix dergleichen hier
)
\Edits: Optimierungen am Code
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel