You've already forked lazarus-ccr
fpsound: Large work to advance the wave reader
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2259 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
33
components/fpsound/example/mainform.lfm
Normal file
33
components/fpsound/example/mainform.lfm
Normal file
@ -0,0 +1,33 @@
|
||||
object Form1: TForm1
|
||||
Left = 323
|
||||
Height = 240
|
||||
Top = 171
|
||||
Width = 320
|
||||
Caption = 'Form1'
|
||||
ClientHeight = 240
|
||||
ClientWidth = 320
|
||||
LCLVersion = '0.9.31'
|
||||
object btnOpenPlayAndClose: TButton
|
||||
Left = 12
|
||||
Height = 25
|
||||
Top = 48
|
||||
Width = 292
|
||||
Caption = 'Open, Play and Close'
|
||||
OnClick = btnOpenPlayAndCloseClick
|
||||
TabOrder = 0
|
||||
end
|
||||
object pathEdit: TFileNameEdit
|
||||
Left = 12
|
||||
Height = 25
|
||||
Top = 13
|
||||
Width = 268
|
||||
FileName = '/home/felipe/Programas/lazarus-ccr/components/fpsound/testsounds/test.wav'
|
||||
DialogOptions = []
|
||||
FilterIndex = 0
|
||||
HideDirectories = False
|
||||
ButtonWidth = 23
|
||||
NumGlyphs = 0
|
||||
MaxLength = 0
|
||||
TabOrder = 1
|
||||
end
|
||||
end
|
46
components/fpsound/example/mainform.pas
Normal file
46
components/fpsound/example/mainform.pas
Normal file
@ -0,0 +1,46 @@
|
||||
unit mainform;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
|
||||
EditBtn;
|
||||
|
||||
type
|
||||
|
||||
{ TForm1 }
|
||||
|
||||
TForm1 = class(TForm)
|
||||
btnOpenPlayAndClose: TButton;
|
||||
pathEdit: TFileNameEdit;
|
||||
procedure btnOpenPlayAndCloseClick(Sender: TObject);
|
||||
private
|
||||
{ private declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
Form1: TForm1;
|
||||
|
||||
implementation
|
||||
|
||||
uses fpsound, fpsound_wav;
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
{ TForm1 }
|
||||
|
||||
procedure TForm1.btnOpenPlayAndCloseClick(Sender: TObject);
|
||||
var
|
||||
lSoundDoc: TSoundDocument;
|
||||
begin
|
||||
lSoundDoc := TSoundDocument.Create;
|
||||
lSoundDoc.LoadFromFile(pathEdit.FileName);
|
||||
lSoundDoc.Free;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
BIN
components/fpsound/example/soundtest.ico
Normal file
BIN
components/fpsound/example/soundtest.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
90
components/fpsound/example/soundtest.lpi
Normal file
90
components/fpsound/example/soundtest.lpi
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="9"/>
|
||||
<General>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<ResourceType Value="res"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
<Icon Value="0"/>
|
||||
</General>
|
||||
<i18n>
|
||||
<EnableI18N LFM="False"/>
|
||||
</i18n>
|
||||
<VersionInfo>
|
||||
<StringTable ProductVersion=""/>
|
||||
</VersionInfo>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="Default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<local>
|
||||
<FormatVersion Value="1"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="2">
|
||||
<Item1>
|
||||
<PackageName Value="fpsound_pkg"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item2>
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
<Filename Value="soundtest.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="soundtest"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="mainform.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="Form1"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="mainform"/>
|
||||
</Unit1>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<Target>
|
||||
<Filename Value="soundtest"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Linking>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerMessages>
|
||||
<MsgFileName Value=""/>
|
||||
</CompilerMessages>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item3>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
21
components/fpsound/example/soundtest.lpr
Normal file
21
components/fpsound/example/soundtest.lpr
Normal file
@ -0,0 +1,21 @@
|
||||
program soundtest;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, mainform
|
||||
{ you can add units after this };
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
RequireDerivedFormResource := True;
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TForm1, Form1);
|
||||
Application.Run;
|
||||
end.
|
||||
|
BIN
components/fpsound/example/soundtest.res
Normal file
BIN
components/fpsound/example/soundtest.res
Normal file
Binary file not shown.
@ -18,31 +18,60 @@ uses
|
||||
type
|
||||
TSoundDocument = class;
|
||||
|
||||
TSoundFormat = (sfWav, sfMP3);
|
||||
TSoundFormat = (sfWav, sfMP3, sfOGG, sfMID, sfAMR, sf3GP, sfMP4);
|
||||
|
||||
{ TSoundReader }
|
||||
|
||||
TSoundReader = class
|
||||
public
|
||||
constructor Create; virtual;
|
||||
procedure ReadFromStream(AStream: TStream; ADest: TSoundDocument); virtual; abstract;
|
||||
end;
|
||||
|
||||
TSoundPlayerKind = (spOpenAL, spMPlayer, spFMod, spExtra1);
|
||||
TSoundPlayerKind = (spOpenAL, spMPlayer, spFMod, spExtra1, spExtra2);
|
||||
|
||||
{ TSoundPlayer }
|
||||
|
||||
TSoundPlayer = class
|
||||
public
|
||||
constructor Create; virtual;
|
||||
procedure Play(ASound: TSoundDocument); virtual; abstract;
|
||||
end;
|
||||
|
||||
// Sound data representation
|
||||
|
||||
TSoundElement = class
|
||||
end;
|
||||
|
||||
// A Key element sets the basic information of the music for the following samples,
|
||||
// such as sample rate. It has no sample data in itself
|
||||
TSoundKeyElement = class(TSoundElement)
|
||||
SampleRate: Cardinal; // example values: 8000, 44100, etc.
|
||||
Channels: Byte; // Number of channels
|
||||
end;
|
||||
|
||||
TSoundSample = class(TSoundElement)
|
||||
ChannelValues: array of Integer;
|
||||
end;
|
||||
|
||||
{ TSoundDocument }
|
||||
|
||||
TSoundDocument = class
|
||||
private
|
||||
AStream: TStream;
|
||||
FPlayer: TSoundPlayer;
|
||||
FSoundData: TFPList; // of TSoundElement
|
||||
public
|
||||
constructor Create; virtual;
|
||||
destructor Destroy; override;
|
||||
// Document read/save methods
|
||||
procedure LoadFromFile(AFileName: string);
|
||||
procedure LoadFromFile(AFileName: string; AFormat: TSoundFormat);
|
||||
class function GuessFormatFromSoundFile(AFileName: string): TSoundFormat;
|
||||
// Document edition methods
|
||||
procedure Clear;
|
||||
procedure AddSoundElement(const AElement: TSoundElement);
|
||||
// Document playing methods
|
||||
procedure Play;
|
||||
procedure Pause;
|
||||
procedure Seek(ANewPos: Double);
|
||||
@ -57,9 +86,9 @@ function GetSoundReader(AFormat: TSoundFormat): TSoundReader;
|
||||
implementation
|
||||
|
||||
var
|
||||
GSoundPlayers: array[TSoundPlayerKind] of TSoundPlayer = (nil, nil, nil, nil);
|
||||
GSoundReader: array[TSoundFormat] of TSoundReader = (nil, nil);
|
||||
// GSoundWriter: array[TSoundFormat] of TSoundWriter = (nil, nil);
|
||||
GSoundPlayers: array[TSoundPlayerKind] of TSoundPlayer = (nil, nil, nil, nil, nil);
|
||||
GSoundReaders: array[TSoundFormat] of TSoundReader = (nil, nil, nil, nil, nil, nil, nil);
|
||||
// GSoundWriter: array[TSoundFormat] of TSoundWriter = (nil, nil, nil, nil, nil, nil, nil);
|
||||
|
||||
procedure RegisterSoundPlayer(APlayer: TSoundPlayer; AKind: TSoundPlayerKind);
|
||||
begin
|
||||
@ -68,44 +97,94 @@ end;
|
||||
|
||||
procedure RegisterSoundReader(AReader: TSoundReader; AFormat: TSoundFormat);
|
||||
begin
|
||||
GSoundReader[AFormat] := AReader;
|
||||
GSoundReaders[AFormat] := AReader;
|
||||
end;
|
||||
|
||||
function GetSoundPlayer(AKind: TSoundPlayerKind): TSoundPlayer;
|
||||
begin
|
||||
|
||||
Result := GSoundPlayers[AKind];
|
||||
end;
|
||||
|
||||
function GetSoundReader(AFormat: TSoundFormat): TSoundReader;
|
||||
begin
|
||||
Result := GSoundReaders[AFormat];
|
||||
end;
|
||||
|
||||
{ TSoundPlayer }
|
||||
|
||||
constructor TSoundPlayer.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
{ TSoundReader }
|
||||
|
||||
constructor TSoundReader.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
{ TSoundDocument }
|
||||
|
||||
constructor TSoundDocument.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
FSoundData := TFPList.Create;
|
||||
end;
|
||||
|
||||
destructor TSoundDocument.Destroy;
|
||||
begin
|
||||
FSoundData.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.LoadFromFile(AFileName: string);
|
||||
var
|
||||
lExt: String;
|
||||
lFormat: TSoundFormat;
|
||||
begin
|
||||
lExt := ExtractFileExt(AFileName);
|
||||
if CompareText(lExt, 'wav') = 0 then LoadFromFile(AFileName, sfWav)
|
||||
else
|
||||
raise Exception.Create(Format('[TSoundDocument.LoadFromFile] Unknown extension: %s', [lExt]));
|
||||
lFormat := GuessFormatFromSoundFile(AFileName);
|
||||
LoadFromFile(AFileName, lFormat);
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.LoadFromFile(AFileName: string; AFormat: TSoundFormat);
|
||||
var
|
||||
lReader: TSoundReader;
|
||||
lStream: TFileStream;
|
||||
begin
|
||||
lReader := GetSoundReader(AFormat);
|
||||
lStream := TFileStream.Create(AFileName, fmOpenRead);
|
||||
try
|
||||
Clear();
|
||||
lReader.ReadFromStream(lStream, Self);
|
||||
finally
|
||||
lStream.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TSoundDocument.GuessFormatFromSoundFile(AFileName: string): TSoundFormat;
|
||||
var
|
||||
lExt: String;
|
||||
begin
|
||||
Result := sfWav;
|
||||
lExt := ExtractFileExt(AFileName);
|
||||
if CompareText(lExt, 'wav') = 0 then Result := sfWav;
|
||||
//raise Exception.Create(Format('[TSoundDocument.LoadFromFile] Unknown extension: %s', [lExt]));
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.Clear;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to FSoundData.Count - 1 do
|
||||
TSoundElement(FSoundData.Items[i]).Free;
|
||||
|
||||
FSoundData.Clear;
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.AddSoundElement(const AElement: TSoundElement);
|
||||
begin
|
||||
FSoundData.Add(AElement);
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.Play;
|
||||
@ -128,5 +207,15 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
var
|
||||
lReaderIndex: TSoundFormat;
|
||||
lPlayerIndex: TSoundPlayerKind;
|
||||
|
||||
finalization
|
||||
for lReaderIndex := Low(TSoundFormat) to High(TSoundFormat) do
|
||||
if GSoundReaders[lReaderIndex] <> nil then GSoundReaders[lReaderIndex].Free;
|
||||
|
||||
for lPlayerIndex := Low(TSoundPlayerKind) to High(TSoundPlayerKind) do
|
||||
if GSoundPlayers[lPlayerIndex] <> nil then GSoundPlayers[lPlayerIndex].Free;
|
||||
end.
|
||||
|
||||
|
@ -302,7 +302,7 @@ begin
|
||||
while (processed > 0) and (processed <= al_bufcount) do
|
||||
begin
|
||||
alSourceUnqueueBuffers(al_source, 1, @buffer);
|
||||
sz:=wave.ReadBuf(al_readbuf^, al_bufsize);
|
||||
//f/ sz:=wave.ReadBuf(al_readbuf^, al_bufsize);
|
||||
if sz <= 0 then
|
||||
begin
|
||||
Exit(False);
|
||||
@ -328,7 +328,7 @@ begin
|
||||
|
||||
for i := 0 to al_bufcount - 1 do
|
||||
begin
|
||||
if wave.ReadBuf(al_readbuf^, al_bufsize) = 0 then
|
||||
//f/ if wave.ReadBuf(al_readbuf^, al_bufsize) = 0 then
|
||||
Break;
|
||||
|
||||
alBufferData(al_buffers[i], al_format, al_readbuf, al_bufsize, al_rate);
|
||||
@ -370,7 +370,7 @@ begin
|
||||
|
||||
// inittialize codec
|
||||
wave:=TWaveReader.Create;
|
||||
if not wave.LoadFromStream(source) then
|
||||
//f/ if not wave.LoadFromStream(source) then
|
||||
raise Exception.Create('[OPCSoundLoadWavFromStream] unable to read WAVE format');
|
||||
|
||||
if wave.fmt.Format<>1 then
|
||||
|
@ -1,4 +1,16 @@
|
||||
{
|
||||
WAV format reader for the fpSound library
|
||||
|
||||
License: The same modified LGPL as the LCL
|
||||
|
||||
Authors:
|
||||
|
||||
JiXian Yang
|
||||
Felipe Monteiro de Carvalho
|
||||
|
||||
Canonical WAV file description here:
|
||||
|
||||
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
|
||||
}
|
||||
unit fpsound_wav;
|
||||
|
||||
@ -7,95 +19,155 @@ unit fpsound_wav;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
Classes, SysUtils, Math,
|
||||
fpsound;
|
||||
|
||||
// WAVE UTILS
|
||||
|
||||
type
|
||||
// WAV is formed by the following structures in this order
|
||||
// All items are in little endian order, except the char arrays
|
||||
// Items might be in big endian order if the RIFF identifier is RIFX
|
||||
|
||||
TRiffHeader = packed record
|
||||
ID : array [0..3] of char;
|
||||
Size : LongWord;
|
||||
Format : array [0..3] of char;
|
||||
ID : array [0..3] of char; // should be RIFF
|
||||
Size : LongWord; // 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size). The entire file size excluding TRiffHeader.ID and .Size
|
||||
Format : array [0..3] of char; // should be WAVE
|
||||
end;
|
||||
|
||||
TWaveFormat = packed record
|
||||
ID : array [0..3] of char;
|
||||
Size : LongWord;
|
||||
Format : Word;
|
||||
Channels : Word;
|
||||
SampleRate : LongWord;
|
||||
ByteRate : LongWord;
|
||||
BlockAlign : Word;
|
||||
BitsPerSample : Word;
|
||||
ID : array [0..3] of char; // Should be "fmt "
|
||||
Size : LongWord; // SubChunk1Size
|
||||
Format : Word; // PCM = 1 (Linear quantization), values > 1 indicate a compressed format
|
||||
Channels : Word; // Mono = 1, Stereo = 2, etc
|
||||
SampleRate : LongWord; // 8000, 44100, etc
|
||||
ByteRate : LongWord; // = SampleRate * NumChannels * BitsPerSample/8
|
||||
BlockAlign : Word; // = NumChannels * BitsPerSample/8
|
||||
BitsPerSample : Word; // examples: 8 bits, 16 bits, etc
|
||||
end;
|
||||
// If the format is not PCM then there will also be:
|
||||
// TWaveFormatExtension = packed record
|
||||
// ExtraParamSize: Word;
|
||||
// ExtraParams...
|
||||
// end;
|
||||
|
||||
TDataChunk = packed record
|
||||
Id : array [0..3] of char;
|
||||
Size : LongWord;
|
||||
Id : array [0..3] of char; // should be "data"
|
||||
Size : LongWord; // == NumSamples * NumChannels * BitsPerSample/8
|
||||
end;
|
||||
// And after this header the actual data comes, which is an array of samples
|
||||
|
||||
{ TWaveReader }
|
||||
|
||||
TWaveReader = class(TObject)
|
||||
private
|
||||
loaded : Boolean;
|
||||
chunkdata : TDataChunk;
|
||||
chunkpos : Int64;
|
||||
pos : Int64;
|
||||
eof : Boolean;
|
||||
TWaveReader = class(TSoundReader)
|
||||
public
|
||||
fmt : TWaveFormat;
|
||||
fStream : TStream;
|
||||
function LoadFromStream(AStream: TStream): Boolean;
|
||||
function ReadBuf(var Buffer; BufferSize: Integer): Integer;
|
||||
fmt: TWaveFormat;
|
||||
datachunk: TDataChunk;
|
||||
NumSamples: Integer;
|
||||
procedure ReadFromStream(AStream: TStream; ADest: TSoundDocument); override;
|
||||
procedure ReadHeaders(AStream: TStream; ADest: TSoundDocument);
|
||||
procedure ReadAllSamples(AStream: TStream; ADest: TSoundDocument);
|
||||
procedure ReadSample(AStream: TStream; ADest: TSoundDocument);
|
||||
procedure ReadChannelData(AStream: TStream; out AValue: Integer);
|
||||
//function ReadBuf(var Buffer; BufferSize: Integer): Integer;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
ID_RIFF = 'RIFF';
|
||||
ID_WAVE = 'WAVE';
|
||||
ID_fmt = 'fmt ';
|
||||
ID_WAVE ='WAVE';
|
||||
fD_fmt = 'fmt ';
|
||||
ID_data = 'data';
|
||||
|
||||
{ TWaveReader }
|
||||
|
||||
function TWaveReader.LoadFromStream(AStream:TStream):Boolean;
|
||||
procedure TWaveReader.ReadFromStream(AStream:TStream; ADest: TSoundDocument);
|
||||
begin
|
||||
ReadHeaders(AStream, ADest);
|
||||
ReadAllSamples(AStream, ADest);
|
||||
end;
|
||||
|
||||
procedure TWaveReader.ReadHeaders(AStream: TStream; ADest: TSoundDocument);
|
||||
var
|
||||
riff : TRiffHeader;
|
||||
lKeyElement: TSoundKeyElement;
|
||||
begin
|
||||
fStream:=AStream;
|
||||
loaded:=True;
|
||||
try
|
||||
Result:=fStream.Read(riff, sizeof(riff))=sizeof(riff);
|
||||
riff.Size:=LEtoN(riff.Size);
|
||||
Result:=Result and (riff.ID=ID_RIFF) and (riff.Format=ID_WAVE);
|
||||
if not Result then Exit;
|
||||
AStream.Read(riff, sizeof(riff));//=sizeof(riff);
|
||||
riff.Size:=LEtoN(riff.Size);
|
||||
//Result:=Result and (riff.ID=ID_RIFF) and (riff.Format=ID_WAVE);
|
||||
//if not Result then Exit;
|
||||
|
||||
Result:=fStream.Read(fmt, sizeof(fmt))=sizeof(fmt);
|
||||
fmt.Size:=LEtoN(fmt.Size);
|
||||
fmt.Format:=LEtoN(fmt.Format);
|
||||
fmt.Channels:=LEtoN(fmt.Channels);
|
||||
fmt.SampleRate:=LEtoN(fmt.SampleRate);
|
||||
fmt.ByteRate:=LEtoN(fmt.ByteRate);
|
||||
fmt.BlockAlign:=LEtoN(fmt.BlockAlign);
|
||||
fmt.BitsPerSample:=LEtoN(fmt.BitsPerSample);
|
||||
AStream.Read(fmt, sizeof(fmt));//=sizeof(fmt);
|
||||
fmt.Size:=LEtoN(fmt.Size);
|
||||
fmt.Format:=LEtoN(fmt.Format);
|
||||
fmt.Channels:=LEtoN(fmt.Channels);
|
||||
fmt.SampleRate:=LEtoN(fmt.SampleRate);
|
||||
fmt.ByteRate:=LEtoN(fmt.ByteRate);
|
||||
fmt.BlockAlign:=LEtoN(fmt.BlockAlign);
|
||||
fmt.BitsPerSample:=LEtoN(fmt.BitsPerSample);
|
||||
|
||||
Result:=fmt.ID=ID_fmt;
|
||||
pos:=-1;
|
||||
except
|
||||
Result:=False;
|
||||
Exit;
|
||||
AStream.Read(datachunk, sizeof(datachunk));
|
||||
datachunk.Size := LEtoN(datachunk.Size);
|
||||
|
||||
NumSamples := fmt.BlockAlign div datachunk.size;
|
||||
|
||||
//Result:=fmt.ID=ID_fmt;
|
||||
// pos:=-1;
|
||||
|
||||
// Store the data in the document
|
||||
lKeyElement := TSoundKeyElement.Create;
|
||||
lKeyElement.SampleRate := fmt.SampleRate;
|
||||
lKeyElement.Channels := fmt.Channels;
|
||||
ADest.AddSoundElement(lKeyElement);
|
||||
end;
|
||||
|
||||
procedure TWaveReader.ReadAllSamples(AStream: TStream; ADest: TSoundDocument);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to NumSamples - 1 do
|
||||
ReadSample(AStream, ADest);
|
||||
end;
|
||||
|
||||
procedure TWaveReader.ReadSample(AStream: TStream; ADest: TSoundDocument);
|
||||
var
|
||||
lSoundSample: TSoundSample;
|
||||
i: Integer;
|
||||
lValue: Integer;
|
||||
begin
|
||||
lSoundSample := TSoundSample.Create;
|
||||
|
||||
SetLength(lSoundSample.ChannelValues, fmt.Channels);
|
||||
for i := 0 to fmt.Channels - 1 do
|
||||
begin
|
||||
ReadChannelData(AStream, lValue);
|
||||
lSoundSample.ChannelValues[i] := lValue;
|
||||
end;
|
||||
|
||||
ADest.AddSoundElement(lSoundSample);
|
||||
end;
|
||||
|
||||
function Min(a,b: Integer): Integer;
|
||||
procedure TWaveReader.ReadChannelData(AStream: TStream; out AValue: Integer);
|
||||
var
|
||||
lByteData: Byte;
|
||||
lWordData: SmallInt;
|
||||
begin
|
||||
if a<b then Result:=a
|
||||
else Result:=b;
|
||||
if fmt.BitsPerSample = 8 then
|
||||
begin
|
||||
lByteData := AStream.ReadByte();
|
||||
AValue := lByteData;
|
||||
end
|
||||
else if fmt.BitsPerSample = 16 then
|
||||
begin
|
||||
AStream.Read(lWordData, 2);
|
||||
AValue := lWordData;
|
||||
end
|
||||
else
|
||||
raise Exception.Create(Format('[TWaveReader.ReadChannelData] Invalid number of bits per sample: %d', [fmt.BitsPerSample]));
|
||||
end;
|
||||
|
||||
function TWaveReader.ReadBuf(var Buffer;BufferSize:Integer):Integer;
|
||||
{function TWaveReader.ReadBuf(var Buffer;BufferSize:Integer):Integer;
|
||||
var
|
||||
sz : Integer;
|
||||
p : PByteArray;
|
||||
@ -135,7 +207,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
Result:=i;
|
||||
end;
|
||||
end;}
|
||||
|
||||
initialization
|
||||
RegisterSoundReader(TWaveReader.Create, sfWav);
|
||||
end.
|
||||
|
||||
|
BIN
components/fpsound/testsounds/defiance_ohio_11.mp3
Normal file
BIN
components/fpsound/testsounds/defiance_ohio_11.mp3
Normal file
Binary file not shown.
BIN
components/fpsound/testsounds/defiance_ohio_11.ogg
Normal file
BIN
components/fpsound/testsounds/defiance_ohio_11.ogg
Normal file
Binary file not shown.
BIN
components/fpsound/testsounds/test.wav
Normal file
BIN
components/fpsound/testsounds/test.wav
Normal file
Binary file not shown.
Reference in New Issue
Block a user