void EncoderVorbis::encodeBuffer(const CSAMPLE *samples, const int size) { float **buffer = vorbis_analysis_buffer(&m_vdsp, size); // Deinterleave samples. We use normalized floats in the engine [-1.0, 1.0] // and libvorbis expects samples in the range [-1.0, 1.0] so no conversion // is required. for (int i = 0; i < size/2; ++i) { buffer[0][i] = samples[i*2]; buffer[1][i] = samples[i*2+1]; } /** encodes audio **/ vorbis_analysis_wrote(&m_vdsp, size/2); /** writes the OGG page and sends it to file or stream **/ writePage(); }
static sf_count_t ogg_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens) { int i, m, j = 0 ; OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; int in_frames = lens / psf->sf.channels ; float **buffer = vorbis_analysis_buffer (&vdata->vd, in_frames) ; for (i = 0 ; i < in_frames ; i++) for (m = 0 ; m < psf->sf.channels ; m++) buffer [m][i] = (float) ptr [j++] ; ogg_write_samples (psf, odata, vdata, in_frames) ; return lens ; } /* ogg_write_d */
static sf_count_t vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t lens) { int i, m, j = 0 ; OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; int in_frames = lens / psf->sf.channels ; float **buffer = vorbis_analysis_buffer (&vdata->vdsp, in_frames) ; for (i = 0 ; i < in_frames ; i++) for (m = 0 ; m < psf->sf.channels ; m++) buffer [m][i] = (float) (ptr [j++]) / 2147483647.0f ; vorbis_write_samples (psf, odata, vdata, in_frames) ; return lens ; } /* vorbis_write_i */
/* Encode the given data into Ogg Vorbis. */ void xmms_ices_encoder_input (encoder_state *s, xmms_samplefloat_t *buf, int bytes) { float **buffer; int i,j; int channels = s->vi.channels; int samples = bytes / (sizeof (xmms_samplefloat_t)*channels); buffer = vorbis_analysis_buffer (&s->vd, samples); for (i = 0; i < samples; i++) for (j = 0; j < channels; j++) buffer[j][i] = buf[i*channels + j]; vorbis_analysis_wrote (&s->vd, samples); s->samples_in_current_page += samples; }
void encode_data_float(encoder_state *s, float **pcm, int samples) { float **buf; int i; buf = vorbis_analysis_buffer(&s->vd, samples); for(i=0; i < s->vi.channels; i++) { memcpy(buf[i], pcm[i], samples*sizeof(float)); } vorbis_analysis_wrote(&s->vd, samples); s->samples_in_current_page += samples; }
void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ float **vorbis_buffer; int count=0,i,j; int sampread=(buff!=NULL)?pdata->periodsize:0; vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); if(!pdata->args.use_jack){ for(i=0;i<sampread;i++){ for(j=0;j<pdata->args.channels;j++){ vorbis_buffer[j][i]=((buff[count+1]<<8)| (0x00ff&(int)buff[count]))/ 32768.f; count+=2; } } } else{ for(j=0;j<pdata->args.channels;j++){ for(i=0;i<sampread;i++){ vorbis_buffer[j][i]=((float*)buff)[count]; count++; } } } vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread); pthread_mutex_lock(&pdata->libogg_mutex); while(vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, &pdata->enc_data->m_vo_block)==1){ vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); while(vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, &pdata->enc_data->m_ogg_pckt2)){ ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, &pdata->enc_data->m_ogg_pckt2); } } pthread_mutex_unlock(&pdata->libogg_mutex); if(!pdata->running)pdata->enc_data->m_ogg_vs.e_o_s=1; pdata->avd-=pdata->periodtime; }
bool ShoutVSTEncoderOGG::Process( float **inputs, long sampleFrames ) { if (!bInitialized) return false; float **buffer=vorbis_analysis_buffer(&vd,sampleFrames); /* uninterleave samples */ for(int i=0;i<sampleFrames;i++){ buffer[0][i] = inputs[0][i]; buffer[1][i] = inputs[1][i]; } /* tell the library how much we actually submitted */ vorbis_analysis_wrote(&vd,sampleFrames); /* vorbis does some data preanalysis, then divvies up blocks for more involved (potentially parallel) processing. Get a single block for encoding now */ int eos = 0; while(vorbis_analysis_blockout(&vd,&vb)==1){ /* analysis, assume we want to use bitrate management */ vorbis_analysis(&vb,NULL); vorbis_bitrate_addblock(&vb); while(vorbis_bitrate_flushpacket(&vd,&op)){ /* weld the packet into the bitstream */ ogg_stream_packetin(&os,&op); /* write out pages (if any) */ while(!eos){ int result=ogg_stream_pageout(&os,&og); if(result==0)break; if (!SendOGGPageToICE(&og)) return false; /* this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) */ if(ogg_page_eos(&og))eos=1; } } } return true; }
int FileVorbis::write_samples(double **buffer, int64_t len) { if(!fd) return 0; float **vorbis_buffer = vorbis_analysis_buffer(&vd, len); for(int i = 0; i < asset->channels; i++) { float *output = vorbis_buffer[i]; double *input = buffer[i]; for(int j = 0; j < len; j++) { output[j] = input[j]; } } vorbis_analysis_wrote(&vd, len); FLUSH_VORBIS return 0; }
void TargetFileOggVorbis::performWrite( const Buffer *buffer, size_t numFrames, size_t frameOffset ) { // process incoming buffer in chunks of maximum mVorbisBufferSize, this prevents memory allocation errors auto currFrame = frameOffset; auto lastFrame = frameOffset + numFrames; while ( currFrame != lastFrame ) { auto numFramesChunk = std::min( mVorbisBufferSize, lastFrame - currFrame ); float ** bufferOgg = vorbis_analysis_buffer( &mVorbisDspState, (int)numFramesChunk ); for ( size_t c = 0; c < getNumChannels(); ++c ) { std::memcpy( bufferOgg[ c ], buffer->getChannel( c ) + currFrame, numFramesChunk * sizeof( float ) ); } vorbis_analysis_wrote( &mVorbisDspState, (int)numFramesChunk ); processAndWriteVorbisBlocks(); currFrame += numFramesChunk; } }
static int output_data(char *readbuffer, int32 bytes) { int i, j, ch = ((dpm.encoding & PE_MONO) ? 1 : 2); double **buffer; int16 *samples = (int16 *)readbuffer; int nsamples = bytes / (2 * ch); ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ /* data to encode */ /* expose the buffer to submit data */ buffer = vorbis_analysis_buffer(&vd, nsamples); /* uninterleave samples */ for(j = 0; j < ch; j++) for(i = 0; i < nsamples; i++) buffer[j][i] = samples[i*ch+j] * (1.0/32768.0); /* tell the library how much we actually submitted */ vorbis_analysis_wrote(&vd, nsamples); /* vorbis does some data preanalysis, then divvies up blocks for more involved (potentially parallel) processing. Get a single block for encoding now */ while(vorbis_analysis_blockout(&vd, &vb) == 1) { /* analysis */ vorbis_analysis(&vb, &op); /* weld the packet into the bitstream */ ogg_stream_packetin(&os, &op); /* write out pages (if any) */ while(ogg_stream_pageout(&os, &og) != 0) { write(dpm.fd, og.header, og.header_len); write(dpm.fd, og.body, og.body_len); } } return 0; }
static bool vorbis_encoder_write(struct encoder *_encoder, const void *data, size_t length, G_GNUC_UNUSED GError **error) { struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; unsigned num_frames; num_frames = length / audio_format_frame_size(&encoder->audio_format); /* this is for only 16-bit audio */ pcm16_to_vorbis_buffer(vorbis_analysis_buffer(&encoder->vd, num_frames), (const int16_t *)data, num_frames, encoder->audio_format.channels); vorbis_analysis_wrote(&encoder->vd, num_frames); vorbis_encoder_blockout(encoder); return true; }
/* * Encode length bytes of audio from the packet into Ogg stream */ PRBool MediaRecorder::EncodeAudio(PRInt16 *a_frames, int len) { int i, j, n; float **a_buffer; /* Uninterleave samples */ n = len / aState->backend->GetFrameSize(); a_buffer = vorbis_analysis_buffer(&aState->vd, n); for (i = 0; i < n; i++){ for (j = 0; j < (int)params->chan; j++) { a_buffer[j][i] = (float)((float)a_frames[i+j] / 32768.f); } } /* Tell libvorbis to do its thing */ vorbis_analysis_wrote(&aState->vd, n); WriteAudio(); return PR_TRUE; }
static int vorbis_write(SWORD *pbuf, size_t nr) { float **buffer; size_t i; size_t amount = (stereo) ? nr / 2 : nr; int result; int eos = 0; buffer = vorbis_analysis_buffer(&vd, (int)amount); for (i = 0; i < amount; i++) { if (stereo == 1) { buffer[0][i]= pbuf[i * 2] / 32768.f; buffer[1][i]= pbuf[(i * 2) + 1] / 32768.f; } else { buffer[0][i]= pbuf[i] / 32768.f; } } vorbis_analysis_wrote(&vd, (int)i); while (vorbis_analysis_blockout(&vd, &vb) == 1) { vorbis_analysis(&vb, NULL); vorbis_bitrate_addblock(&vb); while (vorbis_bitrate_flushpacket(&vd, &op)) { ogg_stream_packetin(&os, &op); while(!eos) { result = ogg_stream_pageout(&os, &og); if (!result) { break; } fwrite(og.header, 1, (size_t)(og.header_len), vorbis_fd); fwrite(og.body, 1, (size_t)(og.body_len), vorbis_fd); if (ogg_page_eos(&og)) { eos = 1; } } } } return 0; }
static void process_frames(void *self) { VORBIS_STREAM *stream; size_t frames; ogg_packet header, header_comm, header_code; float **vorbuf; size_t i, j; stream = (VORBIS_STREAM *)self; frames = stream->header.bookmark; if (stream->header.init == 0) { stream->header.init = 1; vorbis_analysis_headerout(&(stream->vd), &(stream->vc), &header, &header_comm, &header_code); ogg_stream_packetin(&(stream->os), &header); ogg_stream_packetin(&(stream->os), &header_comm); ogg_stream_packetin(&(stream->os), &header_code); while (ogg_stream_flush(&(stream->os), &(stream->og))) vorbis_send(stream); } vorbuf = vorbis_analysis_buffer(&(stream->vd), frames); for (i = 0; i < QMX_CHANNELS; i++) { for (j = 0; j < frames; j++) { vorbuf[i][j] = (float)(distch[i][j]); } } vorbis_analysis_wrote(&(stream->vd), frames); while (vorbis_analysis_blockout(&(stream->vd), &(stream->vb)) == 1) { vorbis_analysis(&(stream->vb), NULL); //&(stream->op)); vorbis_bitrate_addblock(&(stream->vb)); while (vorbis_bitrate_flushpacket(&(stream->vd), &(stream->op))) { ogg_stream_packetin(&(stream->os), &(stream->op)); } } while (ogg_stream_pageout(&(stream->os), &(stream->og))) vorbis_send(stream); stream->header.bookmark = 0; return; }
/*! * \brief Write audio data from a frame to an OGG/Vorbis filestream. * \param fs An OGG/Vorbis filestream. * \param f A frame containing audio to be written to the filestream. * \return -1 if there was an error, 0 on success. */ static int ogg_vorbis_write(struct ast_filestream *fs, struct ast_frame *f) { int i; float **buffer; short *data; struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private; if (!s->writing) { ast_log(LOG_ERROR, "This stream is not set up for writing!\n"); return -1; } if (f->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } if (f->subclass.format.id != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } if (!f->datalen) return -1; data = (short *) f->data.ptr; buffer = vorbis_analysis_buffer(&s->vd, f->samples); for (i = 0; i < f->samples; i++) buffer[0][i] = (double)data[i] / 32768.0; vorbis_analysis_wrote(&s->vd, f->samples); write_stream(s, fs->f); s->writing_pcm_pos += f->samples; return 0; }
static void vorbis_write_real (void * data, gint length) { int samples = length / sizeof (float); int channel, result; float * end = (float *) data + samples; float * * buffer = vorbis_analysis_buffer (& vd, samples / input.channels); float * from, * to; for (channel = 0; channel < input.channels; channel ++) { to = buffer[channel]; for (from = (float *) data + channel; from < end; from += input.channels) * to ++ = * from; } vorbis_analysis_wrote (& vd, samples / input.channels); while(vorbis_analysis_blockout(&vd, &vb) == 1) { vorbis_analysis(&vb, &op); vorbis_bitrate_addblock(&vb); while (vorbis_bitrate_flushpacket(&vd, &op)) { ogg_stream_packetin(&os, &op); while ((result = ogg_stream_pageout(&os, &og))) { if (result == 0) break; write_output(og.header, og.header_len); write_output(og.body, og.body_len); } } } }
/*! * \brief Write audio data from a frame to an OGG/Vorbis filestream. * \param s A OGG/Vorbis filestream. * \param f An frame containing audio to be written to the filestream. * \return -1 ifthere was an error, 0 on success. */ static int ogg_vorbis_write(struct cw_filestream *s, struct cw_frame *f) { int i; float **buffer; short *data; if (!s->writing) { cw_log(LOG_ERROR, "This stream is not set up for writing!\n"); return -1; } if (f->frametype != CW_FRAME_VOICE) { cw_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; } if (f->subclass != CW_FORMAT_SLINEAR) { cw_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass); return -1; } if (!f->datalen) return -1; data = (short *) f->data; buffer = vorbis_analysis_buffer(&s->vd, f->samples); for (i = 0; i < f->samples; i++) buffer[0][i] = data[i]/32768.f; vorbis_analysis_wrote(&s->vd, f->samples); write_stream(s); return 0; }
/*********************************************************************** * Encode *********************************************************************** * **********************************************************************/ static hb_buffer_t* Encode(hb_work_object_t *w) { hb_work_private_t *pv = w->private_data; hb_buffer_t *buf; float **buffer; int i, j; /* Try to extract more data */ if ((buf = Flush(w)) != NULL) { return buf; } /* Check if we need more data */ if (hb_list_bytes(pv->list) < pv->input_samples * sizeof(float)) { return NULL; } /* Process more samples */ hb_list_getbytes(pv->list, pv->buf, pv->input_samples * sizeof(float), &pv->pts, NULL); buffer = vorbis_analysis_buffer(&pv->vd, OGGVORBIS_FRAME_SIZE); for (i = 0; i < OGGVORBIS_FRAME_SIZE; i++) { for (j = 0; j < pv->out_discrete_channels; j++) { buffer[j][i] = ((float*)pv->buf)[(pv->out_discrete_channels * i + pv->remap_table[j])]; } } vorbis_analysis_wrote(&pv->vd, OGGVORBIS_FRAME_SIZE); /* Try to extract again */ return Flush(w); }
void OggWriter::writeFrame( const char * sample, std::size_t nSamples ) { const int SAMPLES = nSamples / sizeof( short int ) / this->getChannels(); const short int * audio = static_cast< const short int * >( static_cast< const void * >( sample ) ); float * * buffer = vorbis_analysis_buffer( this->dsp_.get(), SAMPLES ); if( this->getChannels() == 1 ) { for( int l = 0; l < SAMPLES; ++l ) { buffer[0][l] = audio[l] / 32768.f; } } else { for( int l = 0; l < SAMPLES; ++l ) { buffer[0][l] = audio[l*2] / 32768.f; buffer[1][l] = audio[l*2+1] / 32768.f; } } vorbis_analysis_wrote( this->dsp_.get(), SAMPLES ); while( vorbis_analysis_blockout( this->dsp_.get(), this->block_.get() ) == 1 ) { vorbis_analysis( this->block_.get(), NULL ); vorbis_bitrate_addblock( this->block_.get() ); ogg_packet op; while( vorbis_bitrate_flushpacket( this->dsp_.get(), &op ) ) { ogg_stream_packetin( this->muxer_.get(), &op ); } for(;;) { ogg_page og; int ret = ogg_stream_pageout( this->muxer_.get(), &og ); if( ret == 0 ) { break; } std::fwrite( og.header, 1, og.header_len, this->fout_.get() ); std::fwrite( og.body, 1, og.body_len, this->fout_.get() ); } } }
/* Requires little endian data (currently) */ void encode_data(encoder_state *s, signed char *buf, int bytes, int bigendian) { float **buffer; int i,j; int channels = s->vi.channels; int samples = bytes/(2*channels); buffer = vorbis_analysis_buffer(&s->vd, samples); if(bigendian) { for(i=0; i < samples; i++) { for(j=0; j < channels; j++) { buffer[j][i]=((buf[2*(i*channels + j)]<<8) | (0x00ff&(int)buf[2*(i*channels + j)+1]))/32768.f; } } } else { for(i=0; i < samples; i++) { for(j=0; j < channels; j++) { buffer[j][i]=((buf[2*(i*channels + j) + 1]<<8) | (0x00ff&(int)buf[2*(i*channels + j)]))/32768.f; } } } vorbis_analysis_wrote(&s->vd, samples); s->samples_in_current_page += samples; }
static GstBuffer * _create_audio_buffer (void) { GstBuffer *buffer; ogg_packet packet; float **vorbis_buffer G_GNUC_UNUSED; vorbis_buffer = vorbis_analysis_buffer (&vd, 0); vorbis_analysis_wrote (&vd, 0); vorbis_analysis_blockout (&vd, &vb); vorbis_analysis (&vb, NULL); vorbis_bitrate_addblock (&vb); vorbis_bitrate_flushpacket (&vd, &packet); buffer = gst_buffer_new_and_alloc (packet.bytes); gst_buffer_fill (buffer, 0, packet.packet, packet.bytes); GST_DEBUG ("%p %d", packet.packet, packet.bytes); vorbis_comment_clear (&vc); vorbis_block_clear (&vb); vorbis_dsp_clear (&vd); vorbis_info_clear (&vi); return buffer; }
static void *recordingThreadFct(void *data) { enum { bufInCount=1024, bufInSize=2*bufInCount, }; short int bufIn[bufInSize]; char *bufInBytes=(char*)bufIn; ogg_packet op; RecordingParams *rp=(RecordingParams*)data; int l; while (1) { sb_lock(recBuffer); if (recBuffer->usedCount>=bufInSize) { //buffer contains enough data, let's encode it sb_unlock(recBuffer); sb_retrieveData(recBuffer, bufIn, bufInSize); //convert PCM to OGG library compatible format float **buffer = vorbis_analysis_buffer(&rp->vd, bufInCount); if (rp->vi.channels==1) { for(l=0; l<bufInCount; l++) { buffer[0][l]=((bufInBytes[l*2+1]<<8)|(0x00ff&(int)bufInBytes[l*2]))/32768.f; } } else { for(l=0; l<bufInCount; l++) { buffer[0][l]=((bufInBytes[l*4+1]<<8)|(0x00ff&(int)bufInBytes[l*4]))/32768.f; buffer[1][l]=((bufInBytes[l*4+3]<<8)|(0x00ff&(int)bufInBytes[l*4+2]))/32768.f; } } //encode and write out vorbis_analysis_wrote(&rp->vd, bufInCount); while(vorbis_analysis_blockout(&rp->vd, &rp->vb) == 1) { vorbis_analysis(&rp->vb, NULL); vorbis_bitrate_addblock(&rp->vb); while(vorbis_bitrate_flushpacket(&rp->vd, &op)) { ogg_stream_packetin(&rp->os,&op); ogg_flushall(rp); } } } else { //not much in the buffer, wait for a while to get new data sb_unlock(recBuffer); #ifndef _WIN32 usleep(100*1000); #else Sleep(100); #endif } pthread_mutex_lock(&threadRunMutex); if (threadRunStop) { pthread_mutex_unlock(&threadRunMutex); break; } pthread_mutex_unlock(&threadRunMutex); } //close encoder and output file vorbis_analysis_wrote(&rp->vd, 0); ogg_flushall(rp); vorbis_block_clear(&rp->vb); vorbis_dsp_clear(&rp->vd); vorbis_info_clear(&rp->vi); fclose(rp->outputFile); //empty output buffer pthread_spin_lock(&recBufferLock); sb_destroyBuffer(recBuffer); recBuffer=0; pthread_spin_unlock(&recBufferLock); free(rp); pthread_exit(NULL); return 0; // returns something }
int main(){ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ vorbis_comment vc; /* struct that stores all the user comments */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ int eos=0,ret; int i, founddata; #if defined(macintosh) && defined(__MWERKS__) int argc = 0; char **argv = NULL; argc = ccommand(&argv); /* get a "command line" from the Mac user */ /* this also lets the user set stdin and stdout */ #endif /* we cheat on the WAV header; we just bypass 44 bytes and never verify that it matches 16bit/stereo/44.1kHz. This is just an example, after all. */ #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ /* if we were reading/writing a file, it would also need to in binary mode, eg, fopen("file.wav","wb"); */ /* Beware the evil ifdef. We avoid these where we can, but this one we cannot. Don't add any more, you'll probably go to hell if you do. */ _setmode( _fileno( stdin ), _O_BINARY ); _setmode( _fileno( stdout ), _O_BINARY ); #endif /* we cheat on the WAV header; we just bypass the header and never verify that it matches 16bit/stereo/44.1kHz. This is just an example, after all. */ readbuffer[0] = '\0'; for (i=0, founddata=0; i<30 && ! feof(stdin) && ! ferror(stdin); i++) { fread(readbuffer,1,2,stdin); if ( ! strncmp((char*)readbuffer, "da", 2) ) { founddata = 1; fread(readbuffer,1,6,stdin); break; } } /********** Encode setup ************/ vorbis_info_init(&vi); /* choose an encoding mode. A few possibilities commented out, one actually used: */ /********************************************************************* Encoding using a VBR quality mode. The usable range is -.1 (lowest quality, smallest file) to 1. (highest quality, largest file). Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR ret = vorbis_encode_init_vbr(&vi,2,44100,.4); --------------------------------------------------------------------- Encoding using an average bitrate mode (ABR). example: 44kHz stereo coupled, average 128kbps VBR ret = vorbis_encode_init(&vi,2,44100,-1,128000,-1); --------------------------------------------------------------------- Encode using a quality mode, but select that quality mode by asking for an approximate bitrate. This is not ABR, it is true VBR, but selected using the bitrate interface, and then turning bitrate management off: ret = ( vorbis_encode_setup_managed(&vi,2,44100,-1,128000,-1) || vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE2_SET,NULL) || vorbis_encode_setup_init(&vi)); *********************************************************************/ ret=vorbis_encode_init_vbr(&vi,2,44100,0.1); /* do not continue if setup failed; this can happen if we ask for a mode that libVorbis does not support (eg, too low a bitrate, etc, will return 'OV_EIMPL') */ if(ret)exit(1); /* add a comment */ vorbis_comment_init(&vc); vorbis_comment_add_tag(&vc,"ENCODER","encoder_example.c"); /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init(&vd,&vi); vorbis_block_init(&vd,&vb); /* set up our packet->stream encoder */ /* pick a random serial number; that way we can more likely build chained streams just by concatenation */ srand(time(NULL)); ogg_stream_init(&os,rand()); /* Vorbis streams begin with three headers; the initial header (with most of the codec setup parameters) which is mandated by the Ogg bitstream spec. The second header holds any comment fields. The third header holds the bitstream codebook. We merely need to make the headers, then pass them to libvorbis one at a time; libvorbis handles the additional Ogg bitstream constraints */ { ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); ogg_stream_packetin(&os,&header); /* automatically placed in its own page */ ogg_stream_packetin(&os,&header_comm); ogg_stream_packetin(&os,&header_code); /* This ensures the actual * audio data will start on a new page, as per spec */ while(!eos){ int result=ogg_stream_flush(&os,&og); if(result==0)break; fwrite(og.header,1,og.header_len,stdout); fwrite(og.body,1,og.body_len,stdout); } } while(!eos){ long i; long bytes=fread(readbuffer,1,READ*4,stdin); /* stereo hardwired here */ if(bytes==0){ /* end of file. this can be done implicitly in the mainline, but it's easier to see here in non-clever fashion. Tell the library we're at end of stream so that it can handle the last frame and mark end of stream in the output properly */ vorbis_analysis_wrote(&vd,0); }else{ /* data to encode */ /* expose the buffer to submit data */ float **buffer=vorbis_analysis_buffer(&vd,READ); /* uninterleave samples */ for(i=0;i<bytes/4;i++){ buffer[0][i]=((readbuffer[i*4+1]<<8)| (0x00ff&(int)readbuffer[i*4]))/32768.f; buffer[1][i]=((readbuffer[i*4+3]<<8)| (0x00ff&(int)readbuffer[i*4+2]))/32768.f; } /* tell the library how much we actually submitted */ vorbis_analysis_wrote(&vd,i); } /* vorbis does some data preanalysis, then divvies up blocks for more involved (potentially parallel) processing. Get a single block for encoding now */ while(vorbis_analysis_blockout(&vd,&vb)==1){ /* analysis, assume we want to use bitrate management */ vorbis_analysis(&vb,NULL); vorbis_bitrate_addblock(&vb); while(vorbis_bitrate_flushpacket(&vd,&op)){ /* weld the packet into the bitstream */ ogg_stream_packetin(&os,&op); /* write out pages (if any) */ while(!eos){ int result=ogg_stream_pageout(&os,&og); if(result==0)break; fwrite(og.header,1,og.header_len,stdout); fwrite(og.body,1,og.body_len,stdout); /* this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) */ if(ogg_page_eos(&og))eos=1; } } } } /* clean up and exit. vorbis_info_clear() must be called last */ ogg_stream_clear(&os); vorbis_block_clear(&vb); vorbis_dsp_clear(&vd); vorbis_comment_clear(&vc); vorbis_info_clear(&vi); /* ogg_page and ogg_packet structs always point to storage in libvorbis. They're never freed or manipulated directly */ fprintf(stderr,"Done.\n"); return(0); }
int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ vorbis_info *vi=v->vi; codec_setup_info *ci=vi->codec_setup; if(vals<=0){ int order=32; int i; float *lpc=alloca(order*sizeof(*lpc)); /* if it wasn't done earlier (very short sample) */ if(!v->preextrapolate) _preextrapolate_helper(v); /* We're encoding the end of the stream. Just make sure we have [at least] a few full blocks of zeroes at the end. */ /* actually, we don't want zeroes; that could drop a large amplitude off a cliff, creating spread spectrum noise that will suck to encode. Extrapolate for the sake of cleanliness. */ vorbis_analysis_buffer(v,ci->blocksizes[1]*3); v->eofflag=v->pcm_current; v->pcm_current+=ci->blocksizes[1]*3; for(i=0;i<vi->channels;i++){ if(v->eofflag>order*2){ /* extrapolate with LPC to fill in */ long n; /* make a predictor filter */ n=v->eofflag; if(n>ci->blocksizes[1])n=ci->blocksizes[1]; vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); /* run the predictor filter */ vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); }else{ /* not enough data to extrapolate (unlikely to happen due to guarding the overlap, but bulletproof in case that assumtion goes away). zeroes will do. */ memset(v->pcm[i]+v->eofflag,0, (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i])); } } }else{ if(v->pcm_current+vals>v->pcm_storage) return(OV_EINVAL); v->pcm_current+=vals; /* we may want to reverse extrapolate the beginning of a stream too... in case we're beginning on a cliff! */ /* clumsy, but simple. It only runs once, so simple is good. */ if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) _preextrapolate_helper(v); } return(0); }
/**************************************************************************** * Encode: the whole thing **************************************************************************** * This function spits out ogg packets. ****************************************************************************/ static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf ) { encoder_sys_t *p_sys = p_enc->p_sys; ogg_packet oggpacket; block_t *p_block, *p_chain = NULL; float **buffer; /* FIXME: flush buffers in here */ if( unlikely( !p_aout_buf ) ) return NULL; mtime_t i_pts = p_aout_buf->i_pts - (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay / (mtime_t)p_enc->fmt_in.audio.i_rate; p_sys->i_samples_delay += p_aout_buf->i_nb_samples; buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples ); /* convert samples to float and uninterleave */ for( unsigned int i = 0; i < p_sys->i_channels; i++ ) { for( unsigned int j = 0 ; j < p_aout_buf->i_nb_samples ; j++ ) { buffer[i][j]= ((float *)p_aout_buf->p_buffer) [j * p_sys->i_channels + p_sys->pi_chan_table[i]]; } } vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples ); while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 ) { int i_samples; vorbis_analysis( &p_sys->vb, NULL ); vorbis_bitrate_addblock( &p_sys->vb ); while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) ) { int i_block_size; p_block = block_Alloc( oggpacket.bytes ); memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes ); i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket ); if( i_block_size < 0 ) i_block_size = 0; i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2; p_sys->i_last_block_size = i_block_size; p_block->i_length = (mtime_t)1000000 * (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate; p_block->i_dts = p_block->i_pts = i_pts; p_sys->i_samples_delay -= i_samples; /* Update pts */ i_pts += p_block->i_length; block_ChainAppend( &p_chain, p_block ); } } return p_chain; }
S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname) { #define READ_BUFFER 1024 unsigned char readbuffer[READ_BUFFER*4+44]; /* out of the data segment, not the stack */ /*Flawfinder: ignore*/ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ vorbis_comment vc; /* struct that stores all the user comments */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ int eos=0; int result; U16 num_channels = 0; U32 sample_rate = 0; U32 bits_per_sample = 0; S32 format_error = 0; std::string error_msg; if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg))) { llwarns << error_msg << ": " << in_fname << llendl; return(format_error); } #if 1 unsigned char wav_header[44]; /*Flawfinder: ignore*/ S32 data_left = 0; LLAPRFile infile ; infile.open(in_fname,LL_APR_RB); if (!infile.getFileHandle()) { llwarns << "Couldn't open temporary ogg file for writing: " << in_fname << llendl; return(LLVORBISENC_SOURCE_OPEN_ERR); } LLAPRFile outfile ; outfile.open(out_fname,LL_APR_WPB); if (!outfile.getFileHandle()) { llwarns << "Couldn't open upload sound file for reading: " << in_fname << llendl; return(LLVORBISENC_DEST_OPEN_ERR); } // parse the chunks U32 chunk_length = 0; U32 file_pos = 12; // start at the first chunk (usually fmt but not always) while (infile.eof() != APR_EOF) { infile.seek(APR_SET,file_pos); infile.read(wav_header, 44); chunk_length = ((U32) wav_header[7] << 24) + ((U32) wav_header[6] << 16) + ((U32) wav_header[5] << 8) + wav_header[4]; // llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl; if (!(strncmp((char *)&(wav_header[0]),"fmt ",4))) { num_channels = ((U16) wav_header[11] << 8) + wav_header[10]; sample_rate = ((U32) wav_header[15] << 24) + ((U32) wav_header[14] << 16) + ((U32) wav_header[13] << 8) + wav_header[12]; bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22]; } else if (!(strncmp((char *)&(wav_header[0]),"data",4))) { infile.seek(APR_SET,file_pos+8); // leave the file pointer at the beginning of the data chunk data data_left = chunk_length; break; } file_pos += (chunk_length + 8); chunk_length = 0; } /********** Encode setup ************/ /* choose an encoding mode */ /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */ vorbis_info_init(&vi); // always encode to mono // SL-52913 & SL-53779 determined this quality level to be our 'good // enough' general-purpose quality level with a nice low bitrate. // Equivalent to oggenc -q0.5 F32 quality = 0.05f; // quality = (bitrate==128000 ? 0.4f : 0.1); // if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1)) if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality)) // if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) || // vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) || // vorbis_encode_setup_init(&vi)) { llwarns << "unable to initialize vorbis codec at quality " << quality << llendl; // llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl; return(LLVORBISENC_DEST_OPEN_ERR); } /* add a comment */ vorbis_comment_init(&vc); // vorbis_comment_add(&vc,"Linden"); /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init(&vd,&vi); vorbis_block_init(&vd,&vb); /* set up our packet->stream encoder */ /* pick a random serial number; that way we can more likely build chained streams just by concatenation */ ogg_stream_init(&os, ll_rand()); /* Vorbis streams begin with three headers; the initial header (with most of the codec setup parameters) which is mandated by the Ogg bitstream spec. The second header holds any comment fields. The third header holds the bitstream codebook. We merely need to make the headers, then pass them to libvorbis one at a time; libvorbis handles the additional Ogg bitstream constraints */ { ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); ogg_stream_packetin(&os,&header); /* automatically placed in its own page */ ogg_stream_packetin(&os,&header_comm); ogg_stream_packetin(&os,&header_code); /* We don't have to write out here, but doing so makes streaming * much easier, so we do, flushing ALL pages. This ensures the actual * audio data will start on a new page */ while(!eos){ int result=ogg_stream_flush(&os,&og); if(result==0)break; outfile.write(og.header, og.header_len); outfile.write(og.body, og.body_len); } } while(!eos) { long bytes_per_sample = bits_per_sample/8; long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */ if (bytes==0) { /* end of file. this can be done implicitly in the mainline, but it's easier to see here in non-clever fashion. Tell the library we're at end of stream so that it can handle the last frame and mark end of stream in the output properly */ vorbis_analysis_wrote(&vd,0); // eos = 1; } else { long i; long samples; int temp; data_left -= bytes; /* data to encode */ /* expose the buffer to submit data */ float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER); i = 0; samples = bytes / (num_channels * bytes_per_sample); if (num_channels == 2) { if (bytes_per_sample == 2) { /* uninterleave samples */ for(i=0; i<samples ;i++) { temp = ((signed char *)readbuffer)[i*4+1]; /*Flawfinder: ignore*/ temp += ((signed char *)readbuffer)[i*4+3]; /*Flawfinder: ignore*/ temp <<= 8; temp += readbuffer[i*4]; temp += readbuffer[i*4+2]; buffer[0][i] = ((float)temp) / 65536.f; } } else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard") { /* uninterleave samples */ for(i=0; i<samples ;i++) { temp = readbuffer[i*2+0]; temp += readbuffer[i*2+1]; temp -= 256; buffer[0][i] = ((float)temp) / 256.f; } } } else if (num_channels == 1) { if (bytes_per_sample == 2) { for(i=0; i < samples ;i++) { temp = ((signed char*)readbuffer)[i*2+1]; temp <<= 8; temp += readbuffer[i*2]; buffer[0][i] = ((float)temp) / 32768.f; } } else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard") { for(i=0; i < samples ;i++) { temp = readbuffer[i]; temp -= 128; buffer[0][i] = ((float)temp) / 128.f; } } } /* tell the library how much we actually submitted */ vorbis_analysis_wrote(&vd,i); } /* vorbis does some data preanalysis, then divvies up blocks for more involved (potentially parallel) processing. Get a single block for encoding now */ while(vorbis_analysis_blockout(&vd,&vb)==1) { /* analysis */ /* Do the main analysis, creating a packet */ vorbis_analysis(&vb, NULL); vorbis_bitrate_addblock(&vb); while(vorbis_bitrate_flushpacket(&vd, &op)) { /* weld the packet into the bitstream */ ogg_stream_packetin(&os,&op); /* write out pages (if any) */ while(!eos) { result = ogg_stream_pageout(&os,&og); if(result==0) break; outfile.write(og.header, og.header_len); outfile.write(og.body, og.body_len); /* this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) */ if(ogg_page_eos(&og)) eos=1; } } } } /* clean up and exit. vorbis_info_clear() must be called last */ ogg_stream_clear(&os); vorbis_block_clear(&vb); vorbis_dsp_clear(&vd); vorbis_comment_clear(&vc); vorbis_info_clear(&vi); /* ogg_page and ogg_packet structs always point to storage in libvorbis. They're never freed or manipulated directly */ // fprintf(stderr,"Vorbis encoding: Done.\n"); llinfos << "Vorbis encoding: Done." << llendl; #endif return(LLVORBISENC_NOERR); }
int Encode(void *ctx, int nNumBytesRead, uint8_t* pbtStream) { ogg_context *context = (ogg_context *)ctx; if (!context || !context->callbacks.write) return -1; int eos = 0; int bytes_left = nNumBytesRead; while (bytes_left) { const int channels = 2; const int bits_per_channel = 16; float **buffer = vorbis_analysis_buffer(&context->vorbisDspState, OGG_BLOCK_FRAMES); /* uninterleave samples */ int bytes_per_frame = channels * (bits_per_channel >> 3); int frames = std::min(bytes_left / bytes_per_frame, OGG_BLOCK_FRAMES); int16_t* buf = (int16_t*)pbtStream; for (int i = 0; i < frames; i++) { for (int j = 0; j < channels; j++) buffer[j][i] = (*buf++) / 32768.0f; } pbtStream += frames * bytes_per_frame; bytes_left -= frames * bytes_per_frame; /* tell the library how much we actually submitted */ vorbis_analysis_wrote(&context->vorbisDspState, frames); /* vorbis does some data preanalysis, then divvies up blocks for more involved (potentially parallel) processing. Get a single block for encoding now */ while (vorbis_analysis_blockout(&context->vorbisDspState, &context->vorbisBlock) == 1) { /* analysis, assume we want to use bitrate management */ vorbis_analysis(&context->vorbisBlock, NULL); vorbis_bitrate_addblock(&context->vorbisBlock); ogg_packet packet; ogg_page page; while (vorbis_bitrate_flushpacket(&context->vorbisDspState, &packet)) { /* weld the packet into the bitstream */ ogg_stream_packetin(&context->oggStreamState, &packet); /* write out pages (if any) */ while (!eos) { int result = ogg_stream_pageout(&context->oggStreamState, &page); if (result == 0) break; context->callbacks.write(context->callbacks.opaque, page.header, page.header_len); context->callbacks.write(context->callbacks.opaque, page.body, page.body_len); /* this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) */ if (ogg_page_eos(&page)) eos = 1; } } } } // return bytes consumed return nNumBytesRead - bytes_left; }
int ExportOGG::Export(AudacityProject *project, int numChannels, const wxString &fName, bool selectionOnly, double t0, double t1, MixerSpec *mixerSpec, const Tags *metadata, int WXUNUSED(subformat)) { double rate = project->GetRate(); const TrackList *tracks = project->GetTracks(); double quality = (gPrefs->Read(wxT("/FileFormats/OggExportQuality"), 50)/(float)100.0); wxLogNull logNo; // temporarily disable wxWidgets error messages int updateResult = eProgressSuccess; int eos = 0; FileIO outFile(fName, FileIO::Output); if (!outFile.IsOpened()) { wxMessageBox(_("Unable to open target file for writing")); return false; } // All the Ogg and Vorbis encoding data ogg_stream_state stream; ogg_page page; ogg_packet packet; vorbis_info info; vorbis_comment comment; vorbis_dsp_state dsp; vorbis_block block; // Encoding setup vorbis_info_init(&info); vorbis_encode_init_vbr(&info, numChannels, int(rate + 0.5), quality); // Retrieve tags if (!FillComment(project, &comment, metadata)) { return false; } // Set up analysis state and auxiliary encoding storage vorbis_analysis_init(&dsp, &info); vorbis_block_init(&dsp, &block); // Set up packet->stream encoder. According to encoder example, // a random serial number makes it more likely that you can make // chained streams with concatenation. srand(time(NULL)); ogg_stream_init(&stream, rand()); // First we need to write the required headers: // 1. The Ogg bitstream header, which contains codec setup params // 2. The Vorbis comment header // 3. The bitstream codebook. // // After we create those our responsibility is complete, libvorbis will // take care of any other ogg bistream constraints (again, according // to the example encoder source) ogg_packet bitstream_header; ogg_packet comment_header; ogg_packet codebook_header; vorbis_analysis_headerout(&dsp, &comment, &bitstream_header, &comment_header, &codebook_header); // Place these headers into the stream ogg_stream_packetin(&stream, &bitstream_header); ogg_stream_packetin(&stream, &comment_header); ogg_stream_packetin(&stream, &codebook_header); // Flushing these headers now guarentees that audio data will // start on a NEW page, which apparently makes streaming easier while (ogg_stream_flush(&stream, &page)) { outFile.Write(page.header, page.header_len); outFile.Write(page.body, page.body_len); } const WaveTrackConstArray waveTracks = tracks->GetWaveTrackConstArray(selectionOnly, false); { auto mixer = CreateMixer(waveTracks, tracks->GetTimeTrack(), t0, t1, numChannels, SAMPLES_PER_RUN, false, rate, floatSample, true, mixerSpec); ProgressDialog progress(wxFileName(fName).GetName(), selectionOnly ? _("Exporting the selected audio as Ogg Vorbis") : _("Exporting the entire project as Ogg Vorbis")); while (updateResult == eProgressSuccess && !eos) { float **vorbis_buffer = vorbis_analysis_buffer(&dsp, SAMPLES_PER_RUN); sampleCount samplesThisRun = mixer->Process(SAMPLES_PER_RUN); if (samplesThisRun == 0) { // Tell the library that we wrote 0 bytes - signalling the end. vorbis_analysis_wrote(&dsp, 0); } else { for (int i = 0; i < numChannels; i++) { float *temp = (float *)mixer->GetBuffer(i); memcpy(vorbis_buffer[i], temp, sizeof(float)*SAMPLES_PER_RUN); } // tell the encoder how many samples we have vorbis_analysis_wrote(&dsp, samplesThisRun); } // I don't understand what this call does, so here is the comment // from the example, verbatim: // // vorbis does some data preanalysis, then divvies up blocks // for more involved (potentially parallel) processing. Get // a single block for encoding now while (vorbis_analysis_blockout(&dsp, &block) == 1) { // analysis, assume we want to use bitrate management vorbis_analysis(&block, NULL); vorbis_bitrate_addblock(&block); while (vorbis_bitrate_flushpacket(&dsp, &packet)) { // add the packet to the bitstream ogg_stream_packetin(&stream, &packet); // From vorbis-tools-1.0/oggenc/encode.c: // If we've gone over a page boundary, we can do actual output, // so do so (for however many pages are available). while (!eos) { int result = ogg_stream_pageout(&stream, &page); if (!result) { break; } outFile.Write(page.header, page.header_len); outFile.Write(page.body, page.body_len); if (ogg_page_eos(&page)) { eos = 1; } } } } updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0); } } ogg_stream_clear(&stream); vorbis_block_clear(&block); vorbis_dsp_clear(&dsp); vorbis_info_clear(&info); vorbis_comment_clear(&comment); outFile.Close(); return updateResult; }
nsresult VorbisTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData) { if (mEosSetInEncoder) { return NS_OK; } PROFILER_LABEL("VorbisTrackEncoder", "GetEncodedTrack", js::ProfileEntry::Category::OTHER); nsAutoPtr<AudioSegment> sourceSegment; sourceSegment = new AudioSegment(); { // Move all the samples from mRawSegment to sourceSegment. We only hold // the monitor in this block. ReentrantMonitorAutoEnter mon(mReentrantMonitor); // Wait if mEncoder is not initialized, or when not enough raw data, but is // not the end of stream nor is being canceled. while (!mCanceled && mRawSegment.GetDuration() < GetPacketDuration() && !mEndOfStream) { mon.Wait(); } VORBISLOG("GetEncodedTrack passes wait, duration is %lld\n", mRawSegment.GetDuration()); if (mCanceled || mEncodingComplete) { return NS_ERROR_FAILURE; } sourceSegment->AppendFrom(&mRawSegment); } if (mEndOfStream && (sourceSegment->GetDuration() == 0) && !mEosSetInEncoder) { mEncodingComplete = true; mEosSetInEncoder = true; VORBISLOG("[Vorbis] Done encoding."); vorbis_analysis_wrote(&mVorbisDsp, 0); GetEncodedFrames(aData); return NS_OK; } // Start encoding data. AudioSegment::ChunkIterator iter(*sourceSegment); AudioDataValue **vorbisBuffer = vorbis_analysis_buffer(&mVorbisDsp, (int)sourceSegment->GetDuration()); int framesCopied = 0; AutoTArray<AudioDataValue, 9600> interleavedPcm; AutoTArray<AudioDataValue, 9600> nonInterleavedPcm; interleavedPcm.SetLength(sourceSegment->GetDuration() * mChannels); nonInterleavedPcm.SetLength(sourceSegment->GetDuration() * mChannels); while (!iter.IsEnded()) { AudioChunk chunk = *iter; int frameToCopy = chunk.GetDuration(); if (!chunk.IsNull()) { InterleaveTrackData(chunk, frameToCopy, mChannels, interleavedPcm.Elements() + framesCopied * mChannels); } else { // empty data memset(interleavedPcm.Elements() + framesCopied * mChannels, 0, frameToCopy * mChannels * sizeof(AudioDataValue)); } framesCopied += frameToCopy; iter.Next(); } // De-interleave the interleavedPcm. DeInterleaveTrackData(interleavedPcm.Elements(), framesCopied, mChannels, nonInterleavedPcm.Elements()); // Copy the nonInterleavedPcm to vorbis buffer. for(uint8_t i = 0; i < mChannels; ++i) { memcpy(vorbisBuffer[i], nonInterleavedPcm.Elements() + framesCopied * i, framesCopied * sizeof(AudioDataValue)); } // Now the vorbisBuffer contain the all data in non-interleaved. // Tell the library how much we actually submitted. vorbis_analysis_wrote(&mVorbisDsp, framesCopied); VORBISLOG("vorbis_analysis_wrote framesCopied %d\n", framesCopied); GetEncodedFrames(aData); return NS_OK; }
int oe_encode ( oe_enc_opt* opt ) { ogg_stream_state os; ogg_page og; ogg_packet op; vorbis_dsp_state vd; vorbis_block vb; vorbis_info vi; long samplesdone = 0; int eos; long bytes_written = 0; long packetsdone = 0; int ret = 0; vorbis_info_init ( &vi ); if ( opt->quality >= 0.0f ) { if ( vorbis_encode_init_vbr ( &vi, opt->channels, opt->rate, opt->quality ) ) { vorbis_info_clear ( &vi ); return 1; } } else { if ( vorbis_encode_init ( &vi, opt->channels, opt->rate, opt->max_bitrate > 0 ? opt->max_bitrate * 1000 : -1, opt->bitrate * 1000, opt->min_bitrate > 0 ? opt->min_bitrate * 1000 : -1 ) ) { vorbis_info_clear ( &vi ); return 1; } } vorbis_analysis_init ( &vd, &vi ); vorbis_block_init ( &vd, &vb ); ogg_stream_init ( &os, opt->serialno ); ogg_packet header_main; ogg_packet header_comments; ogg_packet header_codebooks; int result; vorbis_analysis_headerout ( &vd,opt->comments, &header_main, &header_comments, &header_codebooks ); ogg_stream_packetin ( &os, &header_main ); ogg_stream_packetin ( &os, &header_comments ); ogg_stream_packetin ( &os, &header_codebooks ); while ( ( result = ogg_stream_flush ( &os, &og ) ) ) { if ( !result ) break; ret = oe_write_page ( &og, opt->out ); if ( ret != og.header_len + og.body_len ) { ret = 1; goto cleanup; } else bytes_written += ret; } eos = 0; while ( !eos ) { float** buffer = vorbis_analysis_buffer ( &vd, READSIZE ); long samples_read = opt->read_samples ( opt->readdata, buffer, READSIZE ); if ( samples_read == 0 ) vorbis_analysis_wrote ( &vd, 0 ); else { samplesdone += samples_read; vorbis_analysis_wrote ( &vd, samples_read ); } while ( vorbis_analysis_blockout ( &vd, &vb ) == 1 ) { vorbis_analysis ( &vb, NULL ); vorbis_bitrate_addblock ( &vb ); while ( vorbis_bitrate_flushpacket ( &vd, &op ) ) { ogg_stream_packetin ( &os,&op ); packetsdone++; while ( !eos ) { int result = ogg_stream_pageout ( &os, &og ); if ( !result ) break; ret = oe_write_page ( &og, opt->out ); if ( ret != og.header_len + og.body_len ) { ret = 1; goto cleanup; } else bytes_written += ret; if ( ogg_page_eos ( &og ) ) eos = 1; } } } } ret = 0; cleanup: ogg_stream_clear ( &os ); vorbis_block_clear ( &vb ); vorbis_dsp_clear ( &vd ); vorbis_info_clear ( &vi ); return ret; }