📄 beaudio.cxx
字号:
// This function is called by the BMediaRecorder object whenever it has a buffer // with recorded data ready. DETECTVARS(buffer, size/2) DETECTSOUND(); ((CircularBuffer *)cookie)->Fill((const BYTE **)&buffer, &size);}////////////////////////////////////////////////////////////////////////////////// PSoundChannelBeOS// This defines the number of times we would like to be called per second// to play/record data#define PLAYRECFREQ 20 // Macro to let the default buffer size correspond neatly with the// setting we put into the format.#define DEFAULT_BUFSIZE(channels, rate, bits) 480//((channels*rate*(bits/8))/PLAYRECFREQ)PSoundChannelBeOS::PSoundChannelBeOS() : mRecorder(NULL), mPlayer(NULL), mBuffer(NULL), mNumBuffers(1), mResampler(NULL){ PRINT(("default constructor")); InternalSetBuffers(DEFAULT_BUFSIZE(1, 8000, 16),DEFAULT_BUFSIZE(1, 8000, 16)/2); SetFormat(1, 8000, 16); // Nothing else to do here. Notice that the channel is not open for // playing/recording yet.}PSoundChannelBeOS::PSoundChannelBeOS(const PString & dev, Directions dir, unsigned numChannels, unsigned sampleRate, unsigned bitsPerSample) : mRecorder(NULL), mPlayer(NULL), mBuffer(NULL), mNumBuffers(1), mResampler(NULL){ PRINT(("constructor %s %u %u %u", dir==Player ? "Player" : "Recorder", numChannels, sampleRate, bitsPerSample)); InternalSetBuffers(DEFAULT_BUFSIZE(numChannels, sampleRate, bitsPerSample), DEFAULT_BUFSIZE(numChannels, sampleRate, bitsPerSample)/2); Open(dev, dir, numChannels, sampleRate, bitsPerSample); // ignore result; user will need to find out whether this succeeds using IsOpen}PSoundChannelBeOS::~PSoundChannelBeOS(){ PRINT(("")); Close(); // destroys player and recorder InternalSetBuffers(0,0); // destroys buffer}static const PStringArray GetRecorderDevicesList(BMediaRecorder *Recorder){ // Array to hold the list. PStringArray devlist; BMediaRecorder* bRecorder = NULL; if(Recorder != NULL) bRecorder = Recorder;#ifdef MEDIA_KIT_UPDATE BMediaRecorder localRecorder("GetRecorderDevicesList"); bool result=true; status_t status; { if(bRecorder == NULL) { bRecorder = &localRecorder; } if (bRecorder == NULL || bRecorder->InitCheck()!=B_OK) { PRINT(("Error constructing recorder to fetch device names")); result=false; } } if (result) { media_format format; format.type = B_MEDIA_RAW_AUDIO; format.u.raw_audio=media_raw_audio_format::wildcard; // The resampler can only handle 16-bit audio format.u.raw_audio.format=media_raw_audio_format::B_AUDIO_SHORT; // Let the media recorder determine which sources are available if ((status = bRecorder->FetchSources(format, false))!=B_OK) { PRINT(("Couldn't fetch BMediaRecorder sources; status=%d", status)); result=false; } } if (result) { // Fetch the names of all output devices media_format format; BString outname; for (int i=0; i< bRecorder->CountSources(); i++) { if ((status = bRecorder->GetSourceAt(i, &outname, &format))==B_OK) { PRINT(("Device found: %s", outname.String())); devlist[i] = PString(outname.String()); } else { PRINT(("error %d retrieving data for device %d", status, i)); result=false; } } } if (!result) { devlist.RemoveAll(); } return devlist;#else // Media Kit is the only device devlist[0] = "MediaKit"; return devlist;#endif}PStringArray PSoundChannelBeOS::GetDeviceNames(Directions dir){ if (dir==Recorder) { return GetRecorderDevicesList(NULL); } else { // not supported yet return PStringArray("MediaKit"); }}PString PSoundChannelBeOS::GetDefaultDevice(Directions dir){ if (dir==Recorder) { const PStringArray &devlist = GetRecorderDevicesList(NULL); if (devlist.GetSize()!=0) { return devlist[0]; } else { return PString("MediaKit"); } } else { // not supported yet return PString("MediaKit"); }}BOOL PSoundChannelBeOS::OpenPlayer(void){ // We're using cascaded "if result"s here for clarity BOOL result = TRUE;#ifdef FILEDUMP media_format format; format.type=B_MEDIA_RAW_AUDIO; memcpy(&format.u.raw_audio, &mFormat, sizeof(mFormat)); delete playwriter; playwriter=new BAudioFileWriter("play.wav", format, 441000);#endif // Must have a buffer if (!mBuffer) { result = FALSE; PRINT(("Trying to open as player without setting buffers first")); } if (result) { // Create the player //was: mPlayer=new BSoundPlayer(&mFormat, NULL, PlayBuffer, NULL, mBuffer); mPlayer = new BSoundPlayer( &mFormat, NULL, PlayBuffer, NULL, mBuffer); if ((mPlayer == NULL) || (mPlayer->InitCheck() != B_OK)) { result = FALSE; PRINT(("Couldn't construct player")); } } if (result) { // Start the player if (mPlayer->Start() != B_OK) { result = FALSE; PRINT(("Couldn't start the player")); } } if (result) { // Enable the fetching of data by PlayBuffer mPlayer->SetHasData(true); } PRINT(("Returning %s", result?"success":"failure")); return result;}BOOL PSoundChannelBeOS::OpenRecorder(const PString &dev){ // We're using cascaded "if result"s here for clarity BOOL result=TRUE; { if (!mBuffer) { result=FALSE; PRINT(("Trying to open as recorder without setting buffers first")); } } if (result) { // Create the recorder mRecorder=new BMediaRecorder("PWLIB PSoundChannel recorder"); if ((mRecorder==NULL) || (mRecorder->InitCheck()!=B_OK)) { result=FALSE; PRINT(("Couldn't construct recorder")); } }#ifdef MEDIA_KIT_UPDATE int32 sourceindex; if (result) { // Find the specified device in the list of input devices PINDEX x=GetRecorderDevicesList(mRecorder).GetStringsIndex(dev); if (x==P_MAX_INDEX) { result=FALSE; PRINT(("Couldn't find device %s in the list",(const char *)dev)); } else { sourceindex=(int32)x; } } #ifdef _DEBUG if (result) { // Get information for the device BString outname; media_format xformat; status_t err; if ((err=mRecorder->GetSourceAt(sourceindex, &outname, &xformat))==B_OK) { PRINT(("%s", outname.String())); PRINT((" type %d", (int)xformat.type)); PRINT((" AudioFormat 0x%X", (int)xformat.AudioFormat())); PRINT((" u.raw_audio:")); PRINT((" frame_rate: %f", xformat.u.raw_audio.frame_rate)); PRINT((" channel_count: %d", xformat.u.raw_audio.channel_count)); PRINT((" byte_order: %d", xformat.u.raw_audio.byte_order)); PRINT((" buffer_size: %d", xformat.u.raw_audio.buffer_size)); } else { result=FALSE; PRINT(("couldn't get details for source %d: err=0x%X",sourceindex,err)); } }#endif if (result) { // Try to connect to the source if (mRecorder->ConnectSourceAt(sourceindex)!=B_OK) { result=FALSE; PRINT(("Couldn't connect BMediaRecorder to source")); } }#else if (result) { // Connect the recorder to the default input device media_format format; format.type=B_MEDIA_RAW_AUDIO; format.u.raw_audio=media_raw_audio_format::wildcard; // The resampler can only handle 16-bit audio format.u.raw_audio.format=media_raw_audio_format::B_AUDIO_SHORT; if (mRecorder->Connect(format,0)!=B_OK) { result=FALSE; PRINT(("couldn't connect the recorder to the default source")); } }#endif if (result) { // Create resampler media_format format=mRecorder->Format(); delete mResampler; mResampler=new Resampler( format.u.raw_audio.frame_rate, mFormat.frame_rate, format.u.raw_audio.channel_count, mFormat.channel_count, 0, 2);#ifdef FILEDUMP { media_format format; format.type=B_MEDIA_RAW_AUDIO; memcpy(&format.u.raw_audio, &mFormat, sizeof(mFormat)); delete recwriter; recwriter=new BAudioFileWriter("record.wav", format); }#endif // If the current buffer is not a resamplin buffer, re-create it ResamplingBuffer *buf=dynamic_cast<ResamplingBuffer*>(mBuffer); if (buf==NULL) { PRINT(("re-creating buffer")); CircularBuffer *old=mBuffer; mBuffer=new ResamplingBuffer(mResampler, old); delete old; } else { buf->SetResampler(mResampler); } } if (result) { // Set the hook function to our data processing function PRINT(("Setting buffer hook, cookie=%p",mBuffer)); if (mRecorder->SetBufferHook(RecordBuffer, mBuffer)!=B_OK) { result=FALSE; PRINT(("Couldn't set buffer hook on BMediaRecorder")); } } // If something went wrong, delete the recorder. if (!result) { if (mRecorder) { delete mRecorder; mRecorder=NULL; } } return result; }BOOL PSoundChannelBeOS::Open(const PString & dev, Directions dir, unsigned numChannels, unsigned sampleRate, unsigned bitsPerSample){ // We're using cascaded "if result"s here for clarity BOOL result = TRUE; PRINT(("%s %u %u %u", dir==Player?"Player":"Recorder", numChannels, sampleRate, bitsPerSample)); // Close the channel first, just in case Close(); // Initialize the format struct, necessary to create player or recorder if (!SetFormat(numChannels, sampleRate, bitsPerSample)) { result = FALSE; PRINT(("Couldn't set format")); } if (result) { switch (dir) { case Player: PRINT(("... trying to open player")); result=OpenPlayer(); break; case Recorder: PRINT(("...trying to open recorder")); result=OpenRecorder(dev); break; default: PRINT(("Unknown direction parameter")); result=FALSE; } } if (!result) { // If anything went wrong, clean up PRINT(("... can't open, cleaning up")); Close(); } ::snooze(1*1000*1000); PRINT(("Returning %s", result?"success":"failure")); return result;}BOOL PSoundChannelBeOS::Abort(){ return FALSE;}BOOL PSoundChannelBeOS::SetFormat(unsigned numChannels, unsigned sampleRate, unsigned bitsPerSample){ PRINT(("%u %u %u", numChannels, sampleRate, bitsPerSample)); // NOTE: all constructors should call this to initialize // the local members // Do NOT call the function with any parameter set to 0! // The function only fails if the channel is open. // This is because the player or recorder needs to be re-created when the // format changes. if (IsOpen()) { PRINT(("Not allowed to set format on open channel")); return FALSE; } // Initialize the format struct // The numbers of bits that we support here are 8, 16 or 32 bits (signed), // results for other sizes are not defined. mFormat = media_raw_audio_format::wildcard; mFormat.frame_rate=(float)sampleRate; mFormat.channel_count=numChannels; mFormat.format=(bitsPerSample / 8) & 0xF; mFormat.byte_order=B_HOST_IS_BENDIAN ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN; mFormat.buffer_size=DEFAULT_BUFSIZE(numChannels, sampleRate, bitsPerSample); return TRUE;}unsigned PSoundChannelBeOS::GetChannels() const{ return mFormat.channel_count;}unsigned PSoundChannelBeOS::GetSampleRate() const{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -