TargetFileOggVorbis::TargetFileOggVorbis( const DataTargetRef &dataTarget, size_t sampleRate, size_t numChannels, SampleType sampleType ) : cinder::audio::TargetFile( sampleRate, numChannels, sampleType ), mDataTarget( dataTarget ) { CI_ASSERT( mDataTarget ); mStream = mDataTarget->getStream(); vorbis_info_init( &mVorbisInfo ); auto status = vorbis_encode_init_vbr( &mVorbisInfo, getNumChannels(), getSampleRate(), mVorbisBaseQuality ); if ( status ) { throw AudioFormatExc( string( "TargetFileOggVorbis: invalid quality setting." ) ); } vorbis_comment_init( &mVorbisComment ); vorbis_comment_add_tag( &mVorbisComment, "ENCODER", "libcinder" ); vorbis_analysis_init( &mVorbisDspState, &mVorbisInfo ); vorbis_block_init( &mVorbisDspState, &mVorbisBlock ); // a constant stream serial number is used, this is okay since no streams are multiplexed ogg_stream_init( &mOggStream, 0 ); ogg_packet header, headerComment, headerCodebook; vorbis_analysis_headerout( &mVorbisDspState, &mVorbisComment, &header, &headerComment, &headerCodebook ); ogg_stream_packetin( &mOggStream, &header ); ogg_stream_packetin( &mOggStream, &headerComment ); ogg_stream_packetin( &mOggStream, &headerCodebook ); // flush ogg page so audio data starts on a new page while ( ogg_stream_flush( &mOggStream, &mOggPage ) != 0 ) { mStream->writeData( mOggPage.header, mOggPage.header_len ); mStream->writeData( mOggPage.body, mOggPage.body_len ); } }
OutputDeviceNode::OutputDeviceNode( const DeviceRef &device, const Format &format ) : OutputNode( format ), mDevice( device ) { if( ! mDevice ) { string errorMsg = "Empty DeviceRef."; if( ! audio::Device::getDefaultOutput() ) errorMsg += " Also, no default output Device so perhaps there is no available hardware output."; throw AudioDeviceExc( errorMsg ); } // listen to the notifications sent by device property changes in order to update the audio graph. mWillChangeConn = mDevice->getSignalParamsWillChange().connect( bind( &OutputDeviceNode::deviceParamsWillChange, this ) ); mDidChangeConn = mDevice->getSignalParamsDidChange().connect( bind( &OutputDeviceNode::deviceParamsDidChange, this ) ); mInterruptionBeganConn = Context::deviceManager()->getSignalInterruptionBegan().connect( [this] { disable(); } ); mInterruptionEndedConn = Context::deviceManager()->getSignalInterruptionEnded().connect( [this] { enable(); } ); size_t deviceNumChannels = mDevice->getNumOutputChannels(); // If number of channels hasn't been specified, default to 2 (or 1 if that is all that is available). if( getChannelMode() != ChannelMode::SPECIFIED ) { setChannelMode( ChannelMode::SPECIFIED ); setNumChannels( std::min( deviceNumChannels, (size_t)2 ) ); } // Double check the device has enough channels to support what was requested, which may not be the case if the user asked for more than what is available. if( deviceNumChannels < getNumChannels() ) throw AudioFormatExc( string( "Device can not accommodate " ) + to_string( deviceNumChannels ) + " output channels." ); }
OutputDeviceNode::OutputDeviceNode( const DeviceRef &device, const Format &format ) : OutputNode( format ), mDevice( device ) { CI_ASSERT( mDevice ); // listen to the notifications sent by device property changes in order to update the audio graph. mWillChangeConn = mDevice->getSignalParamsWillChange().connect( bind( &OutputDeviceNode::deviceParamsWillChange, this ) ); mDidChangeConn = mDevice->getSignalParamsDidChange().connect( bind( &OutputDeviceNode::deviceParamsDidChange, this ) ); size_t deviceNumChannels = mDevice->getNumOutputChannels(); // If number of channels hasn't been specified, default to 2 (or 1 if that is all that is available). if( getChannelMode() != ChannelMode::SPECIFIED ) { setChannelMode( ChannelMode::SPECIFIED ); setNumChannels( std::min( deviceNumChannels, (size_t)2 ) ); } // Double check the device has enough channels to support what was requested, which may not be the case if the user asked for more than what is available. if( deviceNumChannels < getNumChannels() ) throw AudioFormatExc( string( "Device can not accommodate " ) + to_string( deviceNumChannels ) + " output channels." ); }