📄 beaudio.cxx
字号:
return (unsigned)mFormat.frame_rate;
}
unsigned PSoundChannelBeOS::GetSampleSize() const
{
return (mFormat.format & 0xF)*8; // return number of BITS
}
BOOL PSoundChannelBeOS::Read(void *buf, PINDEX len)
{
PINDEX bufSize = len;
// Can only read from a recorder
if (mRecorder!=NULL)
{
// A Read starts the recording, if it's not running already
if (!mRecorder->IsRunning())
{
mRecorder->Start();
}
// Wait until there's a buffer recorded
mBuffer->WaitForState(CircularBuffer::NotEmpty);
#ifdef FILEDUMP
void *dumpbuf=buf;
size_t dumpsize=len;
#endif
lastReadCount = 0;
while(lastReadCount < bufSize)
{
len = bufSize - lastReadCount;
if(len <= 0)
break;
// Get data from the buffer
mBuffer->Drain((BYTE**)&buf, (size_t*) &len);
lastReadCount += len;
}
#ifdef FILEDUMP
if (recwriter)
{
recwriter->writewavfile(dumpbuf, dumpsize);
}
#endif
return TRUE;
}
return FALSE;
}
BOOL PSoundChannelBeOS::Write(const void *buf, PINDEX len)
{
// can only write to a player
if (mPlayer!=NULL)
{
// Wait until there is space
mBuffer->WaitForState(CircularBuffer::EmptyEnough);
// This function needs to update the last write count
// Store len before it gets modified
lastWriteCount=len;
#ifdef FILEDUMP
if (playwriter)
{
playwriter->writewavfile(buf,len);
}
#endif
// Store data into the buffer
mBuffer->Fill((const BYTE **)&buf, (size_t*) &len);
// Update last write count
lastWriteCount-=len;
return TRUE;
}
return FALSE;
}
BOOL PSoundChannelBeOS::Close()
{
PRINT((""));
// Flush the buffer first
Abort();
// Stop the player
if ((mPlayer!=NULL) && (mPlayer->InitCheck()==B_OK))
{
mPlayer->Stop();
#ifdef FILEDUMP
delete playwriter;
playwriter=NULL;
#endif
}
if(mPlayer)
{
// Destroy the player
delete mPlayer;
mPlayer=NULL; // make sure that another Close won't crash the system
}
// Stop the recorder
if ((mRecorder!=NULL) && (mRecorder->InitCheck()==B_OK))
{
mRecorder->Stop(); // Not really necessary
mRecorder->Disconnect();
#ifdef FILEDUMP
delete recwriter;
recwriter=NULL;
#endif
}
if(mRecorder)
{
// Destroy the recorder
delete mRecorder;
mRecorder=NULL; // make sure that another Close won't crash the system
}
return TRUE;
}
BOOL PSoundChannelBeOS::SetBuffers(PINDEX size, PINDEX count)
{
return InternalSetBuffers(size*(mNumBuffers=count),size);
}
BOOL PSoundChannelBeOS::InternalSetBuffers(PINDEX size, PINDEX threshold)
{
if (mPlayer)
{
mPlayer->SetHasData(false);
}
else if (mRecorder)
{
mRecorder->Stop();
}
// Delete the current buffer
if(mBuffer != NULL)
{
delete mBuffer;
mBuffer = NULL;
}
// Create the new buffer
if (size != 0)
{
if (mRecorder)
{
if (!mResampler)
{
PTRACE(TL, "Creating default resampler");
mResampler = new Resampler(1.0,1.0,1,1,0,1);
}
PTRACE(TL, "Creating resampling buffer, size " << size);
mBuffer = new ResamplingBuffer(mResampler, size, threshold, threshold);
// In case we use resampler, size must be set to resampled buffer size
}
else
{
PTRACE(TL, "Creating playback buffer, size " << size);
mBuffer = new CircularBuffer(size, threshold, threshold);
}
// If we have a player, set the cookie again and restart it
if (mPlayer)
{
mPlayer->SetCookie(mBuffer);
PTRACE(TL, "Tried to set player buffer cookie");
mPlayer->SetHasData(true);
PTRACE(TL, "Tried to set player has data");
}
// If we have a recorder, set the cookie again
// Note that the recorder is not restarted, even if it was running.
// It's not a good idea for the program to change the buffers during
// recording anyway because it would at least lose some data.
if (mRecorder)
{
if(B_OK != mRecorder->SetBufferHook(RecordBuffer, mBuffer))
PTRACE(TL, "Can't set recorder buffer hook");
}
return TRUE;
}
if (IsOpen())
{
PTRACE(TL, "Can't continue without buffers - closing channel");
Close(); // should give errors on subsequent read/writes
}
mBuffer = NULL;
return FALSE;
}
BOOL PSoundChannelBeOS::GetBuffers(PINDEX &size, PINDEX &count)
{
if (mBuffer)
{
size=mBuffer->GetSize();
count=mNumBuffers;
return TRUE;
}
return FALSE;
}
BOOL PSoundChannelBeOS::PlaySound(const PSound &sound, BOOL wait)
{
PRINT(("wait=%s", wait?"true":"false"));
if (mPlayer==NULL)
{
PRINT(("Playing a sound on a closed (or recording) PSoundChannelBeOS"));
return FALSE;
}
#ifdef FILEDUMP
playwriter->writewavfile((void *)(const BYTE*)sound, sound.GetSize());
#endif
// create a local buffer that references the PSound
// NOTE: no conversion between the PSound's format and the
// PSoundChannelBeOS's format is done.
const BYTE *buf=(const BYTE *)sound;
PINDEX size=sound.GetSize();
// Play the sound by doing successive Writes until the sound is done.
// Note that write will return when either the buffer is full or the
// given data is written. We want to return after the entire sound
// has been buffered. So we repeatedly call Write until there is
// no data left
while (size!=0)
{
// Wait until there is space
mBuffer->WaitForState(CircularBuffer::EmptyEnough);
// Write the data
mBuffer->Fill(&buf, (size_t*) &size);
}
// Wait until the sound is finished, if requested
if (wait)
{
PRINT(("Waiting for sound"));
mBuffer->WaitForState(CircularBuffer::Empty);
}
return TRUE;
}
BOOL PSoundChannelBeOS::PlayFile(const PFilePath &file, BOOL wait)
{
entry_ref ref;
status_t err;
// using pointers for these objects so that we don't have to
// construct them here but can nevertheless use the if(ok)'s
BEntry *pentry = NULL;
{
// Create BEntry from file name
pentry = new BEntry(file, true);
err = pentry->InitCheck();
}
if (err==B_OK)
{
// Create entry_ref from BEntry
err = pentry->GetRef(&ref);
}
if (err==B_OK)
{
// Play the sound. Return value is a handle or a negative value for errors
// Errors in BeOS are always negative values
err=play_sound(&ref, true, !wait, wait);
if (err>=0)
{
err=B_OK;
}
}
return (err==B_OK);
}
BOOL PSoundChannelBeOS::HasPlayCompleted()
{
if (mPlayer!=NULL)
{
return mBuffer->IsEmpty();
}
return FALSE;
}
BOOL PSoundChannelBeOS::WaitForPlayCompletion()
{
if (mPlayer!=NULL)
{
mBuffer->WaitForState(CircularBuffer::Empty);
}
return TRUE;
}
BOOL PSoundChannelBeOS::RecordSound(PSound &sound)
{
PRINT((""));
if (mRecorder==NULL)
{
PRINT(("Recording a sound on a closed (or playing) PSoundChannelBeOS"));
return FALSE;
}
// Flush the buffer first
Abort();
// Start recording
if (mRecorder->Start()!=B_OK)
{
PRINT(("BMediaRecorder::Start() returned error"));
return FALSE;
}
// Wait until buffer is filled
mBuffer->WaitForState(CircularBuffer::Full);
PRINT(("Buffer full: size=%lu",mBuffer->GetSize()));
// Stop the recorder
if (mRecorder->Stop()!=B_OK)
{
PRINT(("Uh-oh, recorder is unstoppable!"));
//return FALSE;
}
// Set the sound's format to ours
sound.SetFormat(GetChannels(), GetSampleRate(), GetSampleSize());
// Resize the sound and set up local buffer references
PINDEX size=mBuffer->GetSize();
BYTE *buf=sound.GetPointer(size);
#ifdef FILEDUMP
void *dumpbuf=buf;
size_t dumpsize=size;
#endif
// Read the data
mBuffer->Drain(&buf, (size_t*) &size);
#ifdef FILEDUMP
recwriter->writewavfile(dumpbuf, dumpsize);
#endif
PRINT(("Recording succesful"));
return TRUE;
}
BOOL PSoundChannelBeOS::RecordFile(const PFilePath & filename)
{
// Not implemented for now
return FALSE;
}
BOOL PSoundChannelBeOS::StartRecording()
{
if (mRecorder==NULL)
{
PRINT(("Recording to a closed (or playing) PSoundChannelBeOS"));
return FALSE;
}
// Flush the buffers
Abort();
// Start recording
if (mRecorder->Start()!=B_OK)
{
PRINT(("BMediaRecorder::Start returned error"));
return FALSE;
}
return TRUE;
}
BOOL PSoundChannelBeOS::IsRecordBufferFull()
{
if (mRecorder)
{
return !mBuffer->IsEmpty();
}
return FALSE;
}
BOOL PSoundChannelBeOS::AreAllRecordBuffersFull()
{
if (mRecorder)
{
return mBuffer->IsFull();
}
return FALSE;
}
BOOL PSoundChannelBeOS::WaitForRecordBufferFull()
{
if (mRecorder==NULL)
{
PRINT(("Waiting for record buffer on playing or closed PSoundChannelBeOS"));
return FALSE;
}
mBuffer->WaitForState(CircularBuffer::FullEnough);
return PXSetIOBlock(PXReadBlock, readTimeout);
}
BOOL PSoundChannelBeOS::WaitForAllRecordBuffersFull()
{
if (mRecorder==NULL)
{
PRINT(("Waiting for record buffers on playing or closed PSoundChannelBeOS"));
return FALSE;
}
mBuffer->WaitForState(CircularBuffer::Full);
return TRUE;
}
BOOL PSoundChannelBeOS::IsOpen() const
{
BOOL result=((mPlayer!=NULL) || (mRecorder!=NULL));
PRINT(("returning %s, player 0x%X recorder 0x%X", result?"true":"false", mPlayer, mRecorder));
return result;
}
BOOL PSoundChannelBeOS::SetVolume(unsigned newVolume)
{
#ifdef TODO
cerr << __FILE__<< "PSoundChannelBeOS :: SetVolume called in error. Please fix" << endl;
#endif
return TRUE;
}
BOOL PSoundChannelBeOS::GetVolume(unsigned & volume)
{
#ifdef TODO
cerr << __FILE__<< "PSoundChannelBeOS :: GetVolume called in error. Please fix" << endl;
#endif
return TRUE;
}
// End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -