xue@0: /* xue@0: Harmonic Visualiser xue@0: xue@0: An audio file viewer and editor. xue@0: Centre for Digital Music, Queen Mary, University of London. xue@0: This file copyright 2011 Wen Xue. xue@0: xue@0: This program is free software; you can redistribute it and/or xue@0: modify it under the terms of the GNU General Public License as xue@0: published by the Free Software Foundation; either version 2 of the xue@0: License, or (at your option) any later version. xue@0: */ xue@0: //--------------------------------------------------------------------------- xue@0: #include xue@0: #pragma hdrstop xue@0: xue@0: #include "AudioPac.h" xue@0: #include xue@0: xue@0: #pragma package(smart_init) xue@0: //--------------------------------------------------------------------------- xue@0: void DoubleToInt(void* out, int BytesPerSample, double* in, int Count) xue@0: { xue@0: if (BytesPerSample==1){unsigned char* out8=(unsigned char*)out; for (int k=0; kRead(Buffer, Count); xue@0: } xue@0: xue@0: int __fastcall TAttachFileStream::Seek(int AnOffset, Word Origin) xue@0: { xue@0: if (!File) return 0; xue@0: if (Origin==soFromBeginning) xue@0: return File->Seek(AnOffset+StartOffset, soFromBeginning)-StartOffset; xue@0: else if (Origin==soFromCurrent) xue@0: return File->Seek(AnOffset, soFromCurrent)-StartOffset; xue@0: else xue@0: return File->Seek(AnOffset+EndOffset, soFromEnd)-StartOffset; xue@0: } xue@0: xue@0: __int64 __fastcall TAttachFileStream::Seek(const __int64 AnOffset, TSeekOrigin Origin) xue@0: { xue@0: return Seek((int)AnOffset, (Word)Origin); xue@0: } xue@0: xue@0: int __fastcall TAttachFileStream::Write(const void *Buffer, int Count) xue@0: { xue@0: return File->Write(Buffer, Count); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: // ValidCtrCheck is used to assure that the components created do not have xue@0: // any pure virtual functions. xue@0: // xue@0: xue@0: static inline void ValidCtrCheck(TWaveAudio *) xue@0: { xue@0: new TWaveAudio(NULL); xue@0: } xue@0: //--------------------------------------------------------------------------- xue@0: __fastcall TWaveAudio::~TWaveAudio() xue@0: { xue@0: delete FMemoryStream; xue@0: delete FFileStream; xue@0: DeallocateHWnd(HWndOut); xue@0: DeallocateHWnd(HWndIn); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::Clear(TObject* Sender) xue@0: { xue@0: if (!FUseMemoryStream) xue@0: { xue@0: FUseMemoryStream=true; xue@0: delete FFileStream->File; xue@0: FFileStream->File=0; xue@0: FFileName=""; xue@0: } xue@0: FMemoryStream->Position=0; xue@0: FMemoryStream->Size=0; xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::CloseFile(bool Close) xue@0: { xue@0: if (UseMemoryStream) return; xue@0: int Position=FFileStream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenWrite); xue@0: SaveHeader(FFileStream->File); xue@0: delete FFileStream->File; xue@0: FFileStream->File=0; xue@0: if (!Close) xue@0: { xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenRead); xue@0: FFileStream->Position=Position; xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void TWaveAudio::CopyFrom(TStream* AStream, int Count) xue@0: { xue@0: WaveStream->CopyFrom(AStream, Count); xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: } xue@0: xue@0: void TWaveAudio::CopyFrom(TWaveAudio* AWaveAudio, int Count) xue@0: { xue@0: WaveStream->CopyFrom(AWaveAudio->WaveStream, Count); xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void TWaveAudio::CopySamplesFrom(TStream* AStream, int Count) xue@0: { xue@0: WaveStream->CopyFrom(AStream, Count*FChannels*(BitsPerSample/8)); xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: } xue@0: xue@0: void TWaveAudio::CopySamplesFrom(TWaveAudio* AWaveAudio, int Count) xue@0: { xue@0: WaveStream->CopyFrom(AWaveAudio->WaveStream, Count*FChannels*(BitsPerSample/8)); xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void TWaveAudio::CreateFile(AnsiString FileName) xue@0: { xue@0: UseMemoryStream=false; xue@0: xue@0: TFileStream* OpenFile=new TFileStream(FileName, fmCreate); xue@0: SaveHeader(OpenFile); xue@0: delete OpenFile; xue@0: xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FileName, fmOpenReadWrite); xue@0: FFileStream->StartOffset=FFileStream->File->Size; xue@0: FFileStream->Position=0; xue@0: FFileName=FileName; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: int __fastcall TWaveAudio::FillBlock(void* Block) xue@0: { xue@0: return Stream->Read(Block, FBlockSize); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: int __fastcall TWaveAudio::GetBytesPerSample() xue@0: { xue@0: return FBitsPerSample/8; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: __int32 __fastcall TWaveAudio::GetLength() xue@0: { xue@0: return Stream->Size/FBlockAlign; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: TStream* __fastcall TWaveAudio::GetStream() xue@0: { xue@0: if (FUseMemoryStream) return FMemoryStream; xue@0: else return FFileStream; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void TWaveAudio::GetWaveProperties(TWaveAudio* WaveAudio1) xue@0: { xue@0: FFormatTag=WaveAudio1->FormatTag; xue@0: SamplesPerSec=WaveAudio1->SamplesPerSec; xue@0: BitsPerSample=WaveAudio1->BitsPerSample; xue@0: Channels=WaveAudio1->Channels; xue@0: BlockSize=WaveAudio1->BlockSize; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: bool __fastcall TWaveAudio::ReadHeader(TStream* AStream, __int32& length, bool allowunfinisheddata) xue@0: { xue@0: bool success=true; xue@0: char s[10]; xue@0: __int32 headerlen; xue@0: __int32 headerstart; xue@0: xue@0: __int16 formattag; xue@0: __int16 channels; xue@0: __int32 samplespersec; xue@0: __int32 avgbytespersec; xue@0: __int16 blockalign; xue@0: __int16 bitspersample; xue@0: xue@0: int rc=AStream->Read(s, 4); s[4]=0; xue@0: success=success&&(rc==4)&&!strcmp(s, "RIFF"); xue@0: if (!success) return success; xue@0: xue@0: rc=AStream->Read(&length, 4); xue@0: success=success&&(rc==4); xue@0: xue@0: rc=AStream->Read(s, 4); if (rc!=4) return false; xue@0: s[4]=0; xue@0: success=success&&(rc==4)&&!strcmp(s, "WAVE"); xue@0: if (!success) return success; xue@0: xue@0: rc=AStream->Read(s, 4); s[4]=0; xue@0: while(rc==4 && strcmp(s, "fmt ")) xue@0: { xue@0: AStream->Read(&length, 4); xue@0: AStream->Seek(length, soFromCurrent); xue@0: rc=AStream->Read(s, 4); s[4]=0; xue@0: } xue@0: success=success&&(rc==4); xue@0: if (!success) return success; xue@0: xue@0: rc=AStream->Read(&headerlen, 4); xue@0: headerstart=AStream->Position; xue@0: xue@0: AStream->Read(&formattag, 2); xue@0: AStream->Read(&channels, 2); xue@0: AStream->Read(&samplespersec, 4); xue@0: AStream->Read(&avgbytespersec, 4); xue@0: AStream->Read(&blockalign, 2); xue@0: AStream->Read(&bitspersample, 2); xue@0: success=success&&(formattag==1); xue@0: success=success&&(rc==4)&&(blockalign*8==channels*bitspersample); xue@0: success=success&&(avgbytespersec==samplespersec*blockalign); xue@0: xue@0: if (!success) return success; xue@0: AStream->Seek(headerlen+headerstart, soFromBeginning); xue@0: xue@0: rc=AStream->Read(s, 4); s[4]=0; xue@0: while(rc==4 && strcmp(s, "data")) xue@0: { xue@0: AStream->Read(&length, 4); xue@0: AStream->Seek(length, soFromCurrent); xue@0: rc=AStream->Read(s, 4); s[4]=0; xue@0: } xue@0: success=success&&(rc==4); xue@0: if (!success) return success; xue@0: xue@0: rc=AStream->Read(&length, 4); xue@0: success=success&&(rc==4); xue@0: if (!success) return success; xue@0: xue@0: if (AStream->Position+length>AStream->Size) xue@0: { xue@0: if (allowunfinisheddata) length=(AStream->Size-AStream->Position)/blockalign*blockalign; xue@0: else success=false; xue@0: } xue@0: if (!success) return success; xue@0: xue@0: FFormatTag=formattag; xue@0: FChannels=channels; xue@0: FSamplesPerSec=samplespersec; xue@0: FAvgBytesPerSec=avgbytespersec; xue@0: FBlockAlign=blockalign; xue@0: FBitsPerSample=bitspersample; xue@0: xue@0: return success; xue@0: } xue@0: xue@0: void TWaveAudio::InsertFromFile(AnsiString FileName) xue@0: { xue@0: TFileStream* OpenFile=new TFileStream(FileName, fmOpenRead|fmShareDenyNone); xue@0: xue@0: __int32 length; xue@0: bool success=ReadHeader(OpenFile, length); xue@0: xue@0: if (success) xue@0: { xue@0: FFileName=FileName; xue@0: if (FUseMemoryStream) xue@0: { xue@0: if (length>0) xue@0: { xue@0: FMemoryStream->Size=length; xue@0: OpenFile->Read(FMemoryStream->Memory, length); xue@0: } xue@0: delete OpenFile; xue@0: } xue@0: else xue@0: { xue@0: delete FFileStream->File; xue@0: FFileStream->File=OpenFile; xue@0: FFileStream->StartOffset=OpenFile->Position; xue@0: FFileStream->EndOffset=OpenFile->Position+length-OpenFile->Size; xue@0: } xue@0: xue@0: if (FStreamLimit>0 && Stream->Size>=FStreamLimit && OnStreamFull) OnStreamFull(this); xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: } xue@0: else xue@0: { xue@0: delete OpenFile; xue@0: throw EReadError("PCM error ecountered reading "+FileName); xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: bool TWaveAudio::IsValidWave(AnsiString FileName) xue@0: { xue@0: bool success=true; xue@0: char s[10]; xue@0: __int32 headerlen; xue@0: __int32 headerstart; xue@0: xue@0: __int16 formattag; xue@0: __int16 channels; xue@0: __int32 samplespersec; xue@0: __int32 avgbytespersec; xue@0: __int16 blockalign; xue@0: __int16 bitspersample; xue@0: __int32 length; xue@0: xue@0: xue@0: TFileStream* OpenFile=new TFileStream(FileName,fmOpenRead|fmShareDenyNone); xue@0: xue@0: OpenFile->Read(s, 4); xue@0: s[4]=0; xue@0: success=success&&!strcmp(s, "RIFF"); xue@0: xue@0: OpenFile->Read(&length, 4); xue@0: success=success&&(length+OpenFile->Position==OpenFile->Size); xue@0: xue@0: OpenFile->Read(s, 8); xue@0: s[8]=0; xue@0: success=success&&!strcmp(s, "WAVEfmt "); xue@0: xue@0: OpenFile->Read(&headerlen, 4); xue@0: headerstart=OpenFile->Position; xue@0: xue@0: OpenFile->Read(&formattag, 2); xue@0: success=success&&(formattag==1); xue@0: xue@0: OpenFile->Read(&channels, 2); xue@0: OpenFile->Read(&samplespersec, 4); xue@0: OpenFile->Read(&avgbytespersec, 4); xue@0: OpenFile->Read(&blockalign, 2); xue@0: OpenFile->Read(&bitspersample, 2); xue@0: success=success&&(blockalign*8==channels*bitspersample); xue@0: success=success&&(avgbytespersec==samplespersec*blockalign); xue@0: xue@0: OpenFile->Seek(headerlen+headerstart, soFromBeginning); xue@0: OpenFile->Read(s, 4); xue@0: s[4]=0; xue@0: success=success&&!strcmp(s, "data"); xue@0: xue@0: OpenFile->Read(&length, 4); xue@0: success=success&&(length+OpenFile->Position==OpenFile->Size); xue@0: xue@0: delete OpenFile; xue@0: return success; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void TWaveAudio::LoadFromFile(AnsiString FileName) xue@0: { xue@0: if (FOnBeforeLoad) FOnBeforeLoad(this); xue@0: if (FAutoUseMemoryStream) UseMemoryStream=false; xue@0: if (FUseMemoryStream) FMemoryStream->Clear(); xue@0: InsertFromFile(FileName); xue@0: if (FOnLoad) FOnLoad(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::OnWimClose(TMessage& Message) xue@0: { xue@0: waveInUnprepareHeader(WaveIn,WaveHdr1,sizeof(WAVEHDR)); xue@0: waveInUnprepareHeader(WaveIn,WaveHdr2,sizeof(WAVEHDR)); xue@0: delete WaveHdr1; xue@0: delete WaveHdr2; xue@0: delete[] Buffer1; xue@0: delete[] Buffer2; xue@0: FRecording=false; xue@0: if (ResetInStream && FOnStreamFull) xue@0: FOnStreamFull(this); xue@0: ResetInStream=false; xue@0: ResetInUser=false; xue@0: if (FOnRecordingDone) FOnRecordingDone(this); xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::OnWimData(TMessage& Message) xue@0: { xue@0: WAVEHDR* WaveHdr=(WAVEHDR*)Message.LParam; xue@0: if (!FRecording) return; xue@0: xue@0: if (!ResetInStream) xue@0: { xue@0: ReleaseBlock(WaveHdr->lpData,WaveHdr->dwBytesRecorded); xue@0: if (FStreamLimit>0 && Stream->Size>=FStreamLimit) xue@0: ResetInStream=true; xue@0: waveInAddBuffer(WaveIn,WaveHdr,sizeof(WAVEHDR)); xue@0: if (FOnInAddBuffer) FOnInAddBuffer(this); xue@0: if (ResetInUser) xue@0: { xue@0: waveInReset(WaveIn); xue@0: waveInClose(WaveIn); xue@0: } xue@0: } xue@0: else xue@0: { xue@0: waveInReset(WaveIn); xue@0: waveInClose(WaveIn); xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::OnWimOpen(TMessage& Message) xue@0: { xue@0: // xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::OnWomClose(TMessage& Message) xue@0: { xue@0: waveOutUnprepareHeader(WaveOut,WaveHdr1,sizeof(WAVEHDR)); xue@0: waveOutUnprepareHeader(WaveOut,WaveHdr2,sizeof(WAVEHDR)); xue@0: delete WaveHdr1; xue@0: delete WaveHdr2; xue@0: delete[] Buffer1; xue@0: delete[] Buffer2; xue@0: WaveHdr1=WaveHdr2=0; xue@0: Buffer1=Buffer2=0; xue@0: FPlaying=false; xue@0: FPaused=false; xue@0: ResetOut=false; xue@0: ResetOutUser=false; xue@0: if (FOnPlaybackProgress) FOnPlaybackProgress(this, 1); xue@0: if (FOnPlaybackProg) FOnPlaybackProg(this, -2); xue@0: xue@0: if (OnPlaybackDone) OnPlaybackDone(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::OnWomDone(TMessage& Message) xue@0: { xue@0: WAVEHDR* WaveHdr=(WAVEHDR*)Message.LParam; xue@0: xue@0: if (ResetOut) xue@0: { xue@0: if (WaveHdr->dwBufferLength!=(unsigned)FBlockSize) xue@0: { xue@0: waveOutClose(WaveOut); xue@0: } xue@0: } xue@0: else xue@0: { xue@0: int rc; xue@0: xue@0: if (ResetOutUser) rc=0; xue@0: else rc=FillBlock(WaveHdr->lpData); xue@0: xue@0: if (rc!=FBlockSize) xue@0: { xue@0: ResetOut=true; xue@0: WaveHdr->dwBufferLength=rc; xue@0: if (BitsPerSample==8) memset(&WaveHdr->lpData[rc],0x80,FBlockSize-rc); xue@0: else memset(&WaveHdr->lpData[rc],0,FBlockSize-rc); xue@0: waveOutUnprepareHeader(WaveOut, WaveHdr, sizeof(WAVEHDR)); xue@0: waveOutPrepareHeader(WaveOut, WaveHdr, sizeof(WAVEHDR)); xue@0: } xue@0: waveOutWrite(WaveOut,WaveHdr,sizeof(WAVEHDR)); xue@0: if (FOnPlaybackProgress) xue@0: FOnPlaybackProgress(this, (Stream->Position-FBlockSize)*1.0/Stream->Size); xue@0: if (FOnPlaybackProg) xue@0: FOnPlaybackProg(this, Stream->Position-FBlockSize); xue@0: if (FOnOutWrite) FOnOutWrite(this); xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::OnWomOpen(TMessage& Message) xue@0: { xue@0: // xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::Pause(TObject* Sender) xue@0: { xue@0: if (FPlaying) xue@0: { xue@0: waveOutPause(WaveOut); xue@0: FPaused=true; xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::PausePlayback(TObject* Sender) xue@0: { xue@0: if (Playing) ResetOutUser=true; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::PauseRecording(TObject* Sender) xue@0: { xue@0: if (Recording) ResetInUser=true; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::Play(TObject* Sender) xue@0: { xue@0: Rewind(this); xue@0: StartPlayback(this); xue@0: } xue@0: xue@0: void __fastcall TWaveAudio::Play(TNotifyEvent AnOnPlaybackDone) xue@0: { xue@0: Rewind(this); xue@0: OnPlaybackDone=AnOnPlaybackDone; xue@0: StartPlayback(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: int __fastcall TWaveAudio::Read(void* Buffer, int Count) xue@0: { xue@0: return Stream->Read(Buffer, Count); xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::ReadSamples(void* Buffer, int Count) xue@0: { xue@0: return Stream->Read(Buffer, Count*FChannels*(BitsPerSample/8)); xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::ReadSamples(double* Buffer, int Count) xue@0: { xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: int countavailable=(Stream->Size-Stream->Position)/FBytesPerSample; xue@0: if (Count>countavailable) Count=countavailable; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: IntToDouble(Buffer, &((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Count); xue@0: FMemoryStream->Position=Position+Count*FBytesPerSample; xue@0: } xue@0: else xue@0: { xue@0: void *data=new char[FBlockSize]; xue@0: double *Data=Buffer; xue@0: int CountPF=FBlockSize/FBytesPerSample; xue@0: int Fr=(Count/CountPF); xue@0: for (int i=0; iRead(data, FBlockSize); xue@0: IntToDouble(Data, data, FBytesPerSample, CountPF); xue@0: Data=&Data[CountPF]; xue@0: } xue@0: int CountLastF=Count%CountPF; xue@0: int lastblocksize=CountLastF*FBytesPerSample; xue@0: Stream->Read(data, lastblocksize); xue@0: IntToDouble(Data, data, FBytesPerSample, CountLastF); xue@0: delete[] data; xue@0: } xue@0: xue@0: return Count*FBytesPerSample; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::ReadSamplesInterleave(void* Buffer1, void* Buffer2, int Count) xue@0: { xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: int SampleSize=FBytesPerSample*2; xue@0: int countavailable=(Stream->Size-Stream->Position)/SampleSize; xue@0: if (Count>countavailable) Count=countavailable; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: IntToIntInterleave(Buffer1, Buffer2, FBytesPerSample, &((char*)FMemoryStream->Memory)[Position], Count); xue@0: FMemoryStream->Position=Position+Count*SampleSize; xue@0: } xue@0: else xue@0: { xue@0: void *Data1=Buffer1, *Data2=Buffer2, *data=new char[FBlockSize]; xue@0: int HBlockSize=FBlockSize/2, CountPF=FBlockSize/SampleSize; xue@0: int Fr=Count/CountPF; xue@0: for (int i=0; iRead(data, FBlockSize); xue@0: IntToIntInterleave(Data1, Data2, FBytesPerSample, data, CountPF); xue@0: Data1=&((char*)Data1)[HBlockSize], Data2=&((char*)Data2)[HBlockSize]; xue@0: } xue@0: int CountLastF=Count%CountPF; xue@0: int lastblocksize=CountLastF*SampleSize; xue@0: Stream->Read(data, lastblocksize); xue@0: IntToIntInterleave(Data1, Data2, FBytesPerSample, data, CountLastF); xue@0: delete[] data; xue@0: } xue@0: return Count*SampleSize; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::ReadSamplesInterleave(double* Buffer1, double* Buffer2, int Count) xue@0: { xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: int SampleSize=FBytesPerSample*2; xue@0: int countavailable=(Stream->Size-Stream->Position)/SampleSize; xue@0: if (Count>countavailable) Count=countavailable; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: IntToDoubleInterleave(Buffer1, Buffer2, &((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Count); xue@0: FMemoryStream->Position=Position+Count*SampleSize; xue@0: } xue@0: else xue@0: { xue@0: double *Data1=Buffer1, *Data2=Buffer2; xue@0: void *data=new char[FBlockSize]; xue@0: int CountPF=FBlockSize/SampleSize; xue@0: int Fr=Count/CountPF; xue@0: for (int i=0; iRead(data, FBlockSize); xue@0: IntToDoubleInterleave(Data1, Data2, data, FBytesPerSample, CountPF); xue@0: Data1=&Data1[CountPF], Data2=&Data2[CountPF]; xue@0: } xue@0: int CountLastF=Count%CountPF; xue@0: int lastblocksize=CountLastF*SampleSize; xue@0: Stream->Read(data, lastblocksize); xue@0: IntToDoubleInterleave(Data1, Data2, data, FBytesPerSample, CountLastF); xue@0: delete[] data; xue@0: } xue@0: return Count*SampleSize; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::ReadSamplesMultiSingle(void* Buffer, int Channel, int Count) xue@0: { xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: int SampleSize=FBytesPerSample*FChannels; xue@0: int countavailable=(Stream->Size-Stream->Position)/SampleSize; xue@0: if (Count>countavailable) Count=countavailable; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: IntToIntMultiSingle(Buffer, FBytesPerSample, FChannels, Channel, &((char*)FMemoryStream->Memory)[Position], Count); xue@0: FMemoryStream->Position=Position+Count*SampleSize; xue@0: } xue@0: else xue@0: { xue@0: int CountPF=FBlockSize/SampleSize; xue@0: int ReadSize=CountPF*SampleSize, WriteSize=CountPF*FBytesPerSample; xue@0: int Fr=Count/CountPF; xue@0: void *Data=Buffer, *data=new char[ReadSize]; xue@0: for (int i=0; iRead(data, ReadSize); xue@0: IntToIntMultiSingle(Data, FBytesPerSample, FChannels, Channel, data, CountPF); xue@0: Data=&((char*)Data)[WriteSize]; xue@0: } xue@0: int CountLastF=Count%CountPF; xue@0: ReadSize=CountLastF*SampleSize; xue@0: Stream->Read(data, ReadSize); xue@0: IntToIntMultiSingle(Data, FBytesPerSample, FChannels, Channel, data, CountLastF); xue@0: delete[] data; xue@0: } xue@0: return Count*FBytesPerSample; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::ReadSamplesMultiChannel(int C, void** Buffer, int Count) xue@0: { xue@0: if (C>FChannels) C=FChannels; xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: int SampleSize=FBytesPerSample*FChannels; xue@0: int countavailable=(Stream->Size-Stream->Position)/SampleSize; xue@0: if (Count>countavailable) Count=countavailable; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: IntToIntMultiChannel(C, Buffer, FBytesPerSample, FChannels, &((char*)FMemoryStream->Memory)[Position], Count); xue@0: FMemoryStream->Position=Position+Count*SampleSize; xue@0: } xue@0: else xue@0: { xue@0: int CountPF=FBlockSize/SampleSize; xue@0: int ReadSize=CountPF*SampleSize, WriteSize=CountPF*FBytesPerSample; xue@0: int Fr=Count/CountPF; xue@0: void* data=new char[ReadSize]; xue@0: for (int i=0; iRead(data, ReadSize); xue@0: IntToIntMultiChannel(C, Buffer, FBytesPerSample, FChannels, data, CountPF); xue@0: for (int c=0; cRead(data, ReadSize); xue@0: IntToIntMultiChannel(C, Buffer, FBytesPerSample, FChannels, data, CountLastF); xue@0: } xue@0: return Count*SampleSize; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::ReleaseBlock(void* Block, int BytesRecorded) xue@0: { xue@0: Stream->Write(Block, BytesRecorded); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::Restart(TObject* Sender) xue@0: { xue@0: if (FPlaying) xue@0: { xue@0: waveOutRestart(WaveOut); xue@0: FPaused=false; xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::Rewind(TObject* Sender) xue@0: { xue@0: Stream->Seek(0,soFromBeginning); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SaveHeader(TStream* AStream) xue@0: { xue@0: __int32 s32; xue@0: __int16 s16; xue@0: xue@0: AStream->Write("RIFF",4); xue@0: s32=Stream->Size+38; xue@0: AStream->Write(&s32,4); xue@0: AStream->Write("WAVEfmt ",8); xue@0: s32=0x12; xue@0: AStream->Write(&s32,4); xue@0: s16=FFormatTag; xue@0: AStream->Write(&s16,2); xue@0: s16=FChannels; xue@0: AStream->Write(&s16,2); xue@0: s32=FSamplesPerSec; xue@0: AStream->Write(&s32,4); xue@0: s32=FAvgBytesPerSec; xue@0: AStream->Write(&s32,4); xue@0: s16=FBlockAlign; xue@0: AStream->Write(&s16,2); xue@0: s16=FBitsPerSample; xue@0: AStream->Write(&s16,2); xue@0: s16=0; xue@0: AStream->Write(&s16,2); xue@0: AStream->Write("data",4); xue@0: s32=Stream->Size; xue@0: AStream->Write(&s32,4); xue@0: } xue@0: xue@0: void __fastcall TWaveAudio::SaveToFile(AnsiString FileName) xue@0: { xue@0: TFileStream& SaveFile=*new TFileStream(FileName, fmCreate); xue@0: SaveHeader(&SaveFile); xue@0: xue@0: if (FUseMemoryStream) xue@0: ((TMemoryStream*)Stream)->SaveToStream(&SaveFile); xue@0: else xue@0: SaveFile.CopyFrom(Stream, 0); xue@0: delete &SaveFile; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::Seek(int Offset, WORD Origin) xue@0: { xue@0: WaveStream->Seek(Offset, Origin); xue@0: } xue@0: xue@0: void __fastcall TWaveAudio::SeekSamples(int Offset, WORD Origin) xue@0: { xue@0: WaveStream->Seek(Offset*FChannels*(BitsPerSample/8), Origin); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SetBitsPerSample(__int16 ABitsPerSample) xue@0: { xue@0: if (ABitsPerSample!=8 && ABitsPerSample!=16 && ABitsPerSample!=24) return; xue@0: FBitsPerSample=ABitsPerSample; xue@0: FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8; xue@0: FBlockAlign=FBitsPerSample*FChannels/8; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SetBlockSize(int ABlockSize) xue@0: { xue@0: FBlockSize=ABlockSize; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SetChannels(__int16 AChannels) xue@0: { xue@0: if (AChannels!=1 && AChannels!=2) return; xue@0: FChannels=AChannels; xue@0: FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8; xue@0: FBlockAlign=FBitsPerSample*FChannels/8; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SetLVolume(unsigned __int16 ALVolume) xue@0: { xue@0: if (ALVolume!=FLVolume) xue@0: { xue@0: FLVolume=ALVolume; xue@0: if (FPlaying) SetVolume(); xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SetRVolume(unsigned __int16 ARVolume) xue@0: { xue@0: if (ARVolume!=FRVolume) xue@0: { xue@0: FRVolume=ARVolume; xue@0: if (FPlaying) SetVolume(); xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SetSamplesPerSec(__int32 ASamplesPerSec) xue@0: { xue@0: FSamplesPerSec=ASamplesPerSec; xue@0: FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8; xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::SetStreamLimit(int AStreamLimit) xue@0: { xue@0: if (AStreamLimit>0 && Stream->Size>AStreamLimit) xue@0: { xue@0: if (OnStreamLimitFailure) OnStreamLimitFailure(this); xue@0: return; xue@0: } xue@0: FStreamLimit=AStreamLimit; xue@0: } xue@0: xue@0: void __fastcall TWaveAudio::SetUseMemoryStream(bool AUseMemoryStream) xue@0: { xue@0: if (FUseMemoryStream!=AUseMemoryStream) xue@0: { xue@0: FUseMemoryStream=AUseMemoryStream; xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: MMRESULT __fastcall TWaveAudio::SetVolume(void) xue@0: { xue@0: unsigned __int32 Volume=FRVolume; xue@0: Volume=Volume<<16; xue@0: Volume+=FLVolume; xue@0: return waveOutSetVolume(WaveOut, Volume); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::StartPlayback(TObject* Sender) xue@0: { xue@0: if (FPlaying) return; xue@0: xue@0: WAVEFORMATEX wfx; xue@0: wfx.wFormatTag=FFormatTag; xue@0: wfx.nChannels=FChannels; xue@0: wfx.nSamplesPerSec=FSamplesPerSec; xue@0: wfx.nAvgBytesPerSec=FAvgBytesPerSec; xue@0: wfx.nBlockAlign=FBlockAlign; xue@0: wfx.wBitsPerSample=FBitsPerSample; xue@0: wfx.cbSize=FcbSize; xue@0: xue@0: if (waveOutOpen(&WaveOut,WAVE_MAPPER,&wfx,(DWORD)HWndOut, NULL, xue@0: CALLBACK_WINDOW)!=MMSYSERR_NOERROR) xue@0: { xue@0: throw EWriteError("TWaveAudio Err: Failed opening device WaveOut"); xue@0: } xue@0: xue@0: SetVolume(); xue@0: xue@0: Buffer1=new char[FBlockSize]; xue@0: Buffer2=new char[FBlockSize]; xue@0: WaveHdr1=new WAVEHDR; xue@0: WaveHdr2=new WAVEHDR; xue@0: xue@0: WaveHdr1->lpData=(char*)Buffer1; xue@0: WaveHdr1->dwBufferLength=FBlockSize; xue@0: WaveHdr1->dwBytesRecorded=0; xue@0: WaveHdr1->dwUser=0; xue@0: WaveHdr1->dwFlags=0; xue@0: WaveHdr1->dwLoops=1; xue@0: WaveHdr1->lpNext=NULL; xue@0: WaveHdr1->reserved=0; xue@0: xue@0: WaveHdr2->lpData=(char*)Buffer2; xue@0: WaveHdr2->dwBufferLength=FBlockSize; xue@0: WaveHdr2->dwBytesRecorded=0; xue@0: WaveHdr2->dwUser=0; xue@0: WaveHdr2->dwFlags=0; xue@0: WaveHdr2->dwLoops=1; xue@0: WaveHdr2->lpNext=NULL; xue@0: WaveHdr2->reserved=0; xue@0: xue@0: int rc; xue@0: xue@0: ResetOut=false; xue@0: ResetOutUser=false; xue@0: xue@0: rc=(FillBlock(WaveHdr1->lpData)); xue@0: if (rc!=FBlockSize) xue@0: { xue@0: if (BitsPerSample==8) memset(&WaveHdr1->lpData[rc],0x80,FBlockSize-rc); xue@0: else memset(&WaveHdr1->lpData[rc],0,FBlockSize-rc); xue@0: WaveHdr1->dwBufferLength=rc; xue@0: ResetOut=true; xue@0: } xue@0: waveOutPrepareHeader(WaveOut,WaveHdr1,sizeof(WAVEHDR)); xue@0: waveOutWrite(WaveOut,WaveHdr1,sizeof(WAVEHDR)); xue@0: xue@0: if (FOnPlaybackProgress) xue@0: FOnPlaybackProgress(this, 0); xue@0: if (FOnPlaybackProg) xue@0: FOnPlaybackProg(this, 0); xue@0: xue@0: if (rc==BlockSize) xue@0: { xue@0: rc=(FillBlock(WaveHdr2->lpData)); xue@0: if (rc!=FBlockSize) xue@0: { xue@0: if (BitsPerSample==8) memset(&WaveHdr2->lpData[rc],0x80,FBlockSize-rc); xue@0: else memset(&WaveHdr2->lpData[rc],0,FBlockSize-rc); xue@0: WaveHdr2->dwBufferLength=rc; xue@0: ResetOut=true; xue@0: } xue@0: xue@0: waveOutPrepareHeader(WaveOut,WaveHdr2,sizeof(WAVEHDR)); xue@0: waveOutWrite(WaveOut,WaveHdr2,sizeof(WAVEHDR)); xue@0: xue@0: if (FOnPlaybackProgress) xue@0: FOnPlaybackProgress(this, (Stream->Position-FBlockSize)*1.0/Stream->Size); xue@0: if (FOnPlaybackProg) xue@0: FOnPlaybackProg(this, Stream->Position-FBlockSize); xue@0: xue@0: } xue@0: FPlaying=true; xue@0: if (FOnStartPlayback) FOnStartPlayback(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::StartRecording(TObject* Sender) xue@0: { xue@0: if (FRecording) return; xue@0: xue@0: WAVEFORMATEX wfx; xue@0: wfx.wFormatTag=FFormatTag; xue@0: wfx.nChannels=FChannels; xue@0: wfx.nSamplesPerSec=FSamplesPerSec; xue@0: wfx.nAvgBytesPerSec=FAvgBytesPerSec; xue@0: wfx.nBlockAlign=FBlockAlign; xue@0: wfx.wBitsPerSample=FBitsPerSample; xue@0: wfx.cbSize=FcbSize; xue@0: xue@0: MMRESULT tr=waveInOpen(&WaveIn, WAVE_MAPPER, &wfx, (unsigned long)HWndIn, NULL, xue@0: CALLBACK_WINDOW); xue@0: if (tr!=MMSYSERR_NOERROR && tr!=MMSYSERR_ALLOCATED) xue@0: { xue@0: throw EReadError("TWaveAudio err: Failed opening device WaveIn"); xue@0: } xue@0: xue@0: Buffer1=new char[FBlockSize]; xue@0: Buffer2=new char[FBlockSize]; xue@0: WaveHdr1=new WAVEHDR; xue@0: WaveHdr2=new WAVEHDR; xue@0: xue@0: WaveHdr1->lpData=(char*)Buffer1; xue@0: WaveHdr1->dwBufferLength=FBlockSize; xue@0: WaveHdr1->dwBytesRecorded=0; xue@0: WaveHdr1->dwUser=0; xue@0: WaveHdr1->dwFlags=0; xue@0: WaveHdr1->dwLoops=1; xue@0: WaveHdr1->lpNext=NULL; xue@0: WaveHdr1->reserved=0; xue@0: xue@0: waveInPrepareHeader(WaveIn,WaveHdr1,sizeof(WAVEHDR)); xue@0: xue@0: WaveHdr2->lpData=(char*)Buffer2; xue@0: WaveHdr2->dwBufferLength=FBlockSize; xue@0: WaveHdr2->dwBytesRecorded=0; xue@0: WaveHdr2->dwUser=0; xue@0: WaveHdr2->dwFlags=0; xue@0: WaveHdr2->dwLoops=1; xue@0: WaveHdr2->lpNext=NULL; xue@0: WaveHdr2->reserved=0; xue@0: xue@0: waveInPrepareHeader(WaveIn,WaveHdr2,sizeof(WAVEHDR)); xue@0: xue@0: waveInAddBuffer(WaveIn,WaveHdr1,sizeof(WAVEHDR)); xue@0: waveInAddBuffer(WaveIn,WaveHdr2,sizeof(WAVEHDR)); xue@0: xue@0: ResetInStream=false; xue@0: ResetInUser=false; xue@0: FRecording=true; xue@0: xue@0: waveInStart(WaveIn); xue@0: xue@0: if (FOnStartRecording) FOnStartRecording(this); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: __fastcall TWaveAudio::TWaveAudio(TComponent* Owner) xue@0: : TComponent(Owner) xue@0: { xue@0: FBlockSize=12288; xue@0: FStreamLimit=0; xue@0: FUseMemoryStream=true; xue@0: FAutoUseMemoryStream=true; xue@0: FMemoryStream=new TMemoryStream; xue@0: FFileStream=new TAttachFileStream(NULL); xue@0: xue@0: FPlaying=false; xue@0: FRecording=false; xue@0: FPaused=false; xue@0: xue@0: FOnAudioChange=0; xue@0: FOnStartPlayback=0; xue@0: FOnStartRecording=0; xue@0: FOnPlaybackDone=0; xue@0: FOnRecordingDone=0; xue@0: FOnStreamLimitFailure=0; xue@0: FOnStreamFull=0; xue@0: FOnPlaybackProgress=0; xue@0: FOnPlaybackProg=0; xue@0: FOnInAddBuffer=0; xue@0: FOnOutWrite=0; xue@0: xue@0: FSamplesPerSec=44100; xue@0: FBitsPerSample=16; xue@0: FChannels=1; xue@0: FFileName=""; xue@0: xue@0: FFormatTag=WAVE_FORMAT_PCM; xue@0: FcbSize=0; //ignored for PCM xue@0: FAvgBytesPerSec=FSamplesPerSec*FBitsPerSample*FChannels/8; xue@0: FBlockAlign=FBitsPerSample*FChannels/8; xue@0: xue@0: HWndOut=AllocateHWnd(WaveOutProc); xue@0: HWndIn=AllocateHWnd(WaveInProc); xue@0: xue@0: unsigned long Volume; xue@0: waveOutGetVolume((void *)WAVE_MAPPER, &Volume); xue@0: FLVolume=Volume&0x0000FFFF; xue@0: FRVolume=Volume>>16; xue@0: } xue@0: xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::WaveInProc(TMessage& Message) xue@0: { xue@0: switch(Message.Msg) xue@0: { xue@0: case MM_WIM_OPEN: OnWimOpen(Message); break; xue@0: case MM_WIM_DATA: OnWimData(Message); break; xue@0: case MM_WIM_CLOSE: OnWimClose(Message); break; xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: void __fastcall TWaveAudio::WaveOutProc(TMessage& Message) xue@0: { xue@0: switch(Message.Msg) xue@0: { xue@0: case MM_WOM_OPEN: OnWomOpen(Message); break; xue@0: case MM_WOM_DONE: OnWomDone(Message); break; xue@0: case MM_WOM_CLOSE: OnWomClose(Message); break; xue@0: } xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: int __fastcall TWaveAudio::Write(void* Buffer, int Count) xue@0: { xue@0: if (!FUseMemoryStream) xue@0: { xue@0: int Position=FFileStream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenWrite); xue@0: FFileStream->Position=Position; xue@0: } xue@0: int result=Stream->Write(Buffer, Count); xue@0: if (!FUseMemoryStream) xue@0: { xue@0: int Position=FFileStream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenRead); xue@0: FFileStream->Position=Position; xue@0: } xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: return result; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::WriteSamples(void* Buffer, int Count) xue@0: { xue@0: if (!FUseMemoryStream) xue@0: { xue@0: int Position=FFileStream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenWrite); xue@0: FFileStream->Position=Position; xue@0: } xue@0: int result=Stream->Write(Buffer, Count*FChannels*FBitsPerSample/8); xue@0: if (!FUseMemoryStream) xue@0: { xue@0: int Position=FFileStream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenRead); xue@0: FFileStream->Position=Position; xue@0: } xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: return result; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::WriteSamples(double* Buffer, int Count) xue@0: { xue@0: int result=0; xue@0: if (!FUseMemoryStream) xue@0: { xue@0: int Position=FFileStream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenWrite); xue@0: FFileStream->Position=Position; xue@0: } xue@0: xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: result=Count*FBytesPerSample; xue@0: if (FMemoryStream->SizeSize=Position+result; xue@0: DoubleToInt(&((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Buffer, Count); xue@0: FMemoryStream->Position=Position+result; xue@0: } xue@0: else xue@0: { xue@0: void *data=new char[FBlockSize]; xue@0: double *Data=Buffer; xue@0: int CountPF=FBlockSize/FBytesPerSample; xue@0: int Fr=(Count/CountPF); xue@0: for (int i=0; iWrite(data, FBlockSize); xue@0: Data=&Data[CountPF]; xue@0: } xue@0: int CountLastF=Count%CountPF; xue@0: int lastblocksize=CountLastF*FBytesPerSample; xue@0: DoubleToInt(data, FBytesPerSample, Data, CountLastF); xue@0: result+=Stream->Write(data, lastblocksize); xue@0: delete[] data; xue@0: } xue@0: xue@0: if (!FUseMemoryStream) xue@0: { xue@0: int Position=FFileStream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenRead); xue@0: FFileStream->Position=Position; xue@0: } xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: return result; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::WriteSamplesInterleave(void* Buffer1, void* Buffer2, int Count) xue@0: { xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: int SampleSize=FBytesPerSample*2; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: int countavailable=(FMemoryStream->Size-Position)/SampleSize; xue@0: if (countavailableSize=Position+SampleSize*Count; xue@0: IntToIntInterleave(&((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Buffer1, Buffer2, Count); xue@0: FMemoryStream->Position=Position+SampleSize*Count; xue@0: } xue@0: else xue@0: { xue@0: int Position=Stream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenWrite); xue@0: FFileStream->Position=Position; xue@0: xue@0: int CountPF=FBlockSize/SampleSize, HBlockSize=FBlockSize/2; xue@0: int Fr=Count/CountPF; xue@0: void *Data1=Buffer1, *Data2=Buffer2, *data=new char[FBlockSize]; xue@0: for (int i=0; iWrite(data, FBlockSize); xue@0: Data1=&((char*)Data1)[HBlockSize], Data2=&((char*)Data2)[HBlockSize]; xue@0: } xue@0: int CountLastF=Count%CountPF; xue@0: int lastblocksize=CountLastF*SampleSize; xue@0: IntToIntInterleave(data, FBytesPerSample, Data1, Data2, CountLastF); xue@0: Stream->Write(data, lastblocksize); xue@0: xue@0: Position=Stream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenRead); xue@0: FFileStream->Position=Position; xue@0: } xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: return Count*SampleSize; xue@0: } xue@0: xue@0: int __fastcall TWaveAudio::WriteSamplesInterleave(double* Buffer1, double* Buffer2, int Count) xue@0: { xue@0: int FBytesPerSample=FBitsPerSample/8; xue@0: int SampleSize=FBytesPerSample*2; xue@0: if (FUseMemoryStream) xue@0: { xue@0: int Position=FMemoryStream->Position; xue@0: int countavailable=(FMemoryStream->Size-Position)/SampleSize; xue@0: if (countavailableSize=Position+SampleSize*Count; xue@0: DoubleToIntInterleave(&((char*)FMemoryStream->Memory)[Position], FBytesPerSample, Buffer1, Buffer2, Count); xue@0: FMemoryStream->Position=Position+SampleSize*Count; xue@0: } xue@0: else xue@0: { xue@0: int Position=Stream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenWrite); xue@0: FFileStream->Position=Position; xue@0: xue@0: int CountPF=FBlockSize/SampleSize; xue@0: int Fr=Count/CountPF; xue@0: double *Data1=Buffer1, *Data2=Buffer2; xue@0: void *data=new char[FBlockSize]; xue@0: for (int i=0; iWrite(data, FBlockSize); xue@0: Data1=&Data1[CountPF], Data2=&Data2[CountPF]; xue@0: } xue@0: int CountLastF=Count%CountPF; xue@0: int lastblocksize=CountLastF*SampleSize; xue@0: DoubleToIntInterleave(data, FBytesPerSample, Data1, Data2, CountLastF); xue@0: Stream->Write(data, lastblocksize); xue@0: xue@0: Position=Stream->Position; xue@0: delete FFileStream->File; xue@0: FFileStream->File=new TFileStream(FFileName, fmOpenRead); xue@0: FFileStream->Position=Position; xue@0: } xue@0: if (FOnAudioChange) FOnAudioChange(this); xue@0: return Count*SampleSize; xue@0: } xue@0: //--------------------------------------------------------------------------- xue@0: __fastcall TDataAudio::TDataAudio(TComponent* Owner) xue@0: : TWaveAudio(Owner) xue@0: { xue@0: FCustomFillBlock=0; xue@0: } xue@0: xue@0: int __fastcall TDataAudio::FillBlock(void* Block) xue@0: { xue@0: if (FCustomFillBlock) xue@0: return FCustomFillBlock(Block); xue@0: else xue@0: return TWaveAudio::FillBlock(Block); xue@0: } xue@0: xue@0: //--------------------------------------------------------------------------- xue@0: namespace Audiopac xue@0: { xue@0: void __fastcall PACKAGE Register() xue@0: { xue@0: TComponentClass classes[1] = {__classid(TWaveAudio)}; xue@0: RegisterComponents("Samples", classes, 0); xue@0: } xue@0: } xue@0: //--------------------------------------------------------------------------- xue@0: xue@0: