📄 audio_osx_source.cc
字号:
// UInt32 ACPrimeMethod = kConverterPrimeMethod_None; UInt32 ACPrimeMethod = kConverterPrimeMethod_Pre; propertySize = sizeof (ACPrimeMethod); err = AudioConverterSetProperty (d_AudioConverter, kAudioConverterPrimeMethod, propertySize, &ACPrimeMethod); CheckErrorAndThrow (err, "AudioConverterSetProperty PrimeMethod", "audio_osx_source::audio_osx_source");// Get the size of the I/O buffer(s) to allow for pre-allocated buffers // lead frame info (trail frame info is ignored) AudioConverterPrimeInfo ACPrimeInfo = {0, 0}; propertySize = sizeof (ACPrimeInfo); err = AudioConverterGetProperty (d_AudioConverter, kAudioConverterPrimeInfo, &propertySize, &ACPrimeInfo); CheckErrorAndThrow (err, "AudioConverterGetProperty PrimeInfo", "audio_osx_source::audio_osx_source"); switch (ACPrimeMethod) { case (kConverterPrimeMethod_None): d_leadSizeFrames = d_trailSizeFrames = 0L; break; case (kConverterPrimeMethod_Normal): d_leadSizeFrames = 0L; d_trailSizeFrames = ACPrimeInfo.trailingFrames; break; default: d_leadSizeFrames = ACPrimeInfo.leadingFrames; d_trailSizeFrames = ACPrimeInfo.trailingFrames; } } d_leadSizeBytes = d_leadSizeFrames * sizeof (Float32); d_trailSizeBytes = d_trailSizeFrames * sizeof (Float32); propertySize = sizeof (d_deviceBufferSizeFrames); err = AudioUnitGetProperty (d_InputAU, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, 0, &d_deviceBufferSizeFrames, &propertySize); CheckErrorAndThrow (err, "AudioUnitGetProperty Buffer Frame Size", "audio_osx_source::audio_osx_source"); d_deviceBufferSizeBytes = d_deviceBufferSizeFrames * sizeof (Float32); d_inputBufferSizeBytes = d_deviceBufferSizeBytes + d_leadSizeBytes; d_inputBufferSizeFrames = d_deviceBufferSizeFrames + d_leadSizeFrames;// outBufSizeBytes = floor (inBufSizeBytes * rate_out / rate_in)// since this is rarely exact, we need another buffer to hold// "extra" samples not processed at any given sampling period// this buffer must be at least 4 floats in size, but generally// follows the rule that// extraBufSize = ceil (rate_in / rate_out)*sizeof(float) d_extraBufferSizeFrames = ((UInt32) ceil (d_deviceSampleRate / d_outputSampleRate) * sizeof (float)); if (d_extraBufferSizeFrames < 4) d_extraBufferSizeFrames = 4; d_extraBufferSizeBytes = d_extraBufferSizeFrames * sizeof (float); d_outputBufferSizeFrames = (UInt32) ceil (((Float64) d_inputBufferSizeFrames) * d_outputSampleRate / d_deviceSampleRate); d_outputBufferSizeBytes = d_outputBufferSizeFrames * sizeof (float); d_inputBufferSizeFrames += d_extraBufferSizeFrames;// pre-alloc all buffers AllocAudioBufferList (&d_InputBuffer, d_n_deviceChannels, d_inputBufferSizeBytes); if (d_passThrough == false) { AllocAudioBufferList (&d_OutputBuffer, d_n_max_channels, d_outputBufferSizeBytes); } else { d_OutputBuffer = d_InputBuffer; }// create the stuff to regulate I/O d_cond_data = new mld_condition (); if (d_cond_data == NULL) CheckErrorAndThrow (errno, "new mld_condition (data)", "audio_osx_source::audio_osx_source"); d_internal = d_cond_data->mutex ();// initialize the AU for input err = AudioUnitInitialize (d_InputAU); CheckErrorAndThrow (err, "AudioUnitInitialize", "audio_osx_source::audio_osx_source");#if _OSX_AU_DEBUG_ fprintf (stderr, "audio_osx_source Parameters:\n"); fprintf (stderr, " Device Sample Rate is %g\n", d_deviceSampleRate); fprintf (stderr, " User Sample Rate is %g\n", d_outputSampleRate); fprintf (stderr, " Max Sample Count is %ld\n", d_max_sample_count); fprintf (stderr, " # Device Channels is %ld\n", d_n_deviceChannels); fprintf (stderr, " # Max Channels is %ld\n", d_n_max_channels); fprintf (stderr, " Device Buffer Size is Frames = %ld\n", d_deviceBufferSizeFrames); fprintf (stderr, " Lead Size is Frames = %ld\n", d_leadSizeFrames); fprintf (stderr, " Trail Size is Frames = %ld\n", d_trailSizeFrames); fprintf (stderr, " Input Buffer Size is Frames = %ld\n", d_inputBufferSizeFrames); fprintf (stderr, " Output Buffer Size is Frames = %ld\n", d_outputBufferSizeFrames);#endif}voidaudio_osx_source::AllocAudioBufferList (AudioBufferList** t_ABL, UInt32 n_channels, UInt32 bufferSizeBytes){ FreeAudioBufferList (t_ABL); UInt32 propertySize = (offsetof (AudioBufferList, mBuffers[0]) + (sizeof (AudioBuffer) * n_channels)); *t_ABL = (AudioBufferList*) calloc (1, propertySize); (*t_ABL)->mNumberBuffers = n_channels; int counter = n_channels; while (--counter >= 0) { (*t_ABL)->mBuffers[counter].mNumberChannels = 1; (*t_ABL)->mBuffers[counter].mDataByteSize = bufferSizeBytes; (*t_ABL)->mBuffers[counter].mData = calloc (1, bufferSizeBytes); }}voidaudio_osx_source::FreeAudioBufferList (AudioBufferList** t_ABL){// free pre-allocated audio buffer, if it exists if (*t_ABL != NULL) { int counter = (*t_ABL)->mNumberBuffers; while (--counter >= 0) free ((*t_ABL)->mBuffers[counter].mData); free (*t_ABL); (*t_ABL) = 0; }}bool audio_osx_source::IsRunning (){ UInt32 AURunning = 0, AUSize = sizeof (UInt32); OSStatus err = AudioUnitGetProperty (d_InputAU, kAudioOutputUnitProperty_IsRunning, kAudioUnitScope_Global, 0, &AURunning, &AUSize); CheckErrorAndThrow (err, "AudioUnitGetProperty IsRunning", "audio_osx_source::IsRunning"); return (AURunning);}bool audio_osx_source::start (){ if (! IsRunning ()) { OSStatus err = AudioOutputUnitStart (d_InputAU); CheckErrorAndThrow (err, "AudioOutputUnitStart", "audio_osx_source::start"); } return (true);}bool audio_osx_source::stop (){ if (IsRunning ()) { OSStatus err = AudioOutputUnitStop (d_InputAU); CheckErrorAndThrow (err, "AudioOutputUnitStart", "audio_osx_source::stop"); for (UInt32 n = 0; n < d_n_user_channels; n++) { d_buffers[n]->abort (); } } return (true);}audio_osx_source::~audio_osx_source (){ OSStatus err = noErr;// stop the AudioUnit stop();#if _OSX_DO_LISTENERS_// remove the listeners err = AudioUnitRemovePropertyListener (d_InputAU, kAudioUnitProperty_StreamFormat, (AudioUnitPropertyListenerProc) UnitListener); CheckError (err, "~audio_osx_source: AudioUnitRemovePropertyListener"); err = AudioHardwareRemovePropertyListener (kAudioHardwarePropertyDefaultInputDevice, (AudioHardwarePropertyListenerProc) HardwareListener); CheckError (err, "~audio_osx_source: AudioHardwareRemovePropertyListener");#endif// free pre-allocated audio buffers FreeAudioBufferList (&d_InputBuffer); if (d_passThrough == false) { err = AudioConverterDispose (d_AudioConverter); CheckError (err, "~audio_osx_source: AudioConverterDispose"); FreeAudioBufferList (&d_OutputBuffer); }// remove the audio unit err = AudioUnitUninitialize (d_InputAU); CheckError (err, "~audio_osx_source: AudioUnitUninitialize"); err = CloseComponent (d_InputAU); CheckError (err, "~audio_osx_source: CloseComponent");// empty and delete the queues for (UInt32 n = 0; n < d_n_max_channels; n++) { delete d_buffers[n]; d_buffers[n] = 0; } delete [] d_buffers; d_buffers = 0;// close and delete the control stuff delete d_cond_data;}audio_osx_source_sptraudio_osx_make_source (int sampling_freq, const std::string device_name, bool do_block, int channel_config, int max_sample_count){ return audio_osx_source_sptr (new audio_osx_source (sampling_freq, device_name, do_block, channel_config, max_sample_count));}boolaudio_osx_source::check_topology (int ninputs, int noutputs){// check # inputs to make sure it's valid if (ninputs != 0) { fprintf (stderr, "audio_osx_source::check_topology(): " "number of input streams provided (%d) should be 0.\n", ninputs); throw std::runtime_error ("audio_osx_source::check_topology()"); }// check # outputs to make sure it's valid if ((noutputs < 1) | (noutputs > (int) d_n_max_channels)) { fprintf (stderr, "audio_osx_source::check_topology(): " "number of output streams provided (%d) should be in " "[1,%ld] for the selected audio device.\n", noutputs, d_n_max_channels); throw std::runtime_error ("audio_osx_source::check_topology()"); }// save the actual number of output (user) channels d_n_user_channels = noutputs;#if _OSX_AU_DEBUG_ fprintf (stderr, "chk_topo: Actual # user output channels = %d\n", noutputs);#endif return (true);}intaudio_osx_source::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items){ // acquire control to do processing here only d_internal->lock ();#if _OSX_AU_DEBUG_ fprintf (stderr, "work1: SC = %4ld, #OI = %4d, #Chan = %ld\n", d_queueSampleCount, noutput_items, output_items.size());#endif // set the actual # of output items to the 'desired' amount then // verify that data is available; if not enough data is available, // either wait until it is (is "do_block" is true), return (0) is no // data is available and "do_block" is false, or process the actual // amount of available data. UInt32 actual_noutput_items = noutput_items; if (d_queueSampleCount < actual_noutput_items) { if (d_queueSampleCount == 0) { // no data; do_block decides what to do if (d_do_block == true) { while (d_queueSampleCount == 0) { // release control so-as to allow data to be retrieved; // block until there is data to return d_cond_data->wait (); // the condition's signal() was called; acquire control to // keep thread safe } } else { // no data & not blocking; return nothing // release control so-as to allow data to be retrieved d_internal->unlock (); return (0); } } // use the actual amount of available data actual_noutput_items = d_queueSampleCount; } // number of channels int l_counter = (int) output_items.size(); // copy the items from the circular buffer(s) to 'work's output buffers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -