int EncoderVorbis::initEncoder(int bitrate, int samplerate) { vorbis_info_init(&m_vinfo); // initialize VBR quality based mode int ret = vorbis_encode_init(&m_vinfo, 2, samplerate, -1, bitrate*1000, -1); if (ret == 0) { initStream(); } else { ret = -1; }; return ret; }
static int tc_vorbis_configure(TCModuleInstance *self, const char *options, vob_t *vob) { VorbisPrivateData *pd = NULL; int samplerate = (vob->mp3frequency) ? vob->mp3frequency : vob->a_rate; float quality = TC_CLAMP(vob->mp3quality, 0.0, 9.9) / 10.0; int ret, br = vob->mp3bitrate * 1000; TC_MODULE_SELF_CHECK(self, "configure"); pd = self->userdata; if (vob->dm_bits != 16) { tc_log_error(MOD_NAME, "Only 16-bit samples supported"); return TC_ERROR; } pd->flush_flag = vob->encoder_flush; pd->end_of_stream = TC_FALSE; pd->channels = vob->dm_chan; pd->bits = vob->dm_bits; pd->packets = 0; pd->frames = 0; vorbis_info_init(&pd->vi); if (quality > ZERO_QUALITY) { ret = vorbis_encode_init_vbr(&pd->vi, pd->channels, samplerate, quality); } else { ret = vorbis_encode_init(&pd->vi, pd->channels, samplerate, -1, br, -1); } if (ret) { tc_log_error(MOD_NAME, "the Vorbis encoder could not set up a mode" " according to the requested settings."); ret = TC_ERROR; } else { vorbis_comment_init(&pd->vc); vorbis_comment_add_tag(&pd->vc, "ENCODER", PACKAGE " " VERSION); vorbis_analysis_init(&pd->vd, &pd->vi); vorbis_block_init(&pd->vd, &pd->vb); ret = tc_ogg_new_extradata(pd); if (ret == TC_OK) { /* publish it */ vob->ex_a_xdata = &(pd->xdata); } } return ret; }
static int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) { #ifdef OGGVORBIS_VBR_BY_ESTIMATE /* variable bitrate by estimate */ return (vorbis_encode_setup_managed(vi, avccontext->channels, avccontext->sample_rate, -1, avccontext->bit_rate, -1) || vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL) || vorbis_encode_setup_init(vi)) ; #else /* constant bitrate */ return vorbis_encode_init(vi, avccontext->channels, avccontext->sample_rate, -1, avccontext->bit_rate, -1) ; #endif }
/* Create an ogg stream and vorbis encoder, with the configuration * specified in the encoder_state. */ static gboolean xmms_ices_encoder_create (encoder_state *s, vorbis_comment *vc) { ogg_packet header[3]; if (s->encoder_inited) { XMMS_DBG ("OOPS: xmms_ices_encoder_create called " "with s->encoder_inited == TRUE !"); } XMMS_DBG ("Creating encoder in ABR mode: min/avg/max bitrate %d/%d/%d", s->min_br, s->nom_br, s->max_br); /* Create the Vorbis encoder. */ vorbis_info_init (&s->vi); if (vorbis_encode_init (&s->vi, s->channels, s->rate, s->max_br, s->nom_br, s->min_br) < 0) return FALSE; vorbis_analysis_init (&s->vd, &s->vi); vorbis_block_init (&s->vd, &s->vb); /* Initialize the ogg stream and input the vorbis header * packets. */ ogg_stream_init (&s->os, s->serial++); vorbis_analysis_headerout (&s->vd, vc, &header[0], &header[1], &header[2]); ogg_stream_packetin (&s->os, &header[0]); ogg_stream_packetin (&s->os, &header[1]); ogg_stream_packetin (&s->os, &header[2]); s->in_header = TRUE; s->flushing = FALSE; s->samples_in_current_page = 0; s->previous_granulepos = 0; s->encoder_inited = TRUE; return TRUE; }
static bool vorbis_encoder_reinit(struct vorbis_encoder *encoder, GError **error) { vorbis_info_init(&encoder->vi); if (encoder->quality >= -1.0) { /* a quality was configured (VBR) */ if (0 != vorbis_encode_init_vbr(&encoder->vi, encoder->audio_format.channels, encoder->audio_format.sample_rate, encoder->quality * 0.1)) { g_set_error(error, vorbis_encoder_quark(), 0, "error initializing vorbis vbr"); vorbis_info_clear(&encoder->vi); return false; } } else { /* a bit rate was configured */ if (0 != vorbis_encode_init(&encoder->vi, encoder->audio_format.channels, encoder->audio_format.sample_rate, -1.0, encoder->bitrate * 1000, -1.0)) { g_set_error(error, vorbis_encoder_quark(), 0, "error initializing vorbis encoder"); vorbis_info_clear(&encoder->vi); return false; } } vorbis_analysis_init(&encoder->vd, &encoder->vi); vorbis_block_init(&encoder->vd, &encoder->vb); ogg_stream_init(&encoder->os, g_random_int()); return true; }
StreamEncoder::StreamEncoder() { //Initialize the info vorbis_info_init(&mVorbisInfo); if (ErrorCheck(vorbis_encode_init(&mVorbisInfo, 2, 44100, 100, 80, 60)) == true) { //Error Write("vorbis_encode_init error"); return; } if (ErrorCheck(vorbis_analysis_init(&mVorbisDspState, &mVorbisInfo)) == true) { //Error Write("vorbis_analysis_init error"); return; } vorbis_comment_init(&mVorbisComment); //vorbis_comment_add(&mVorbisComment, "Comments"); int vahCode = vorbis_analysis_headerout(&mVorbisDspState, &mVorbisComment, &mOggPacketIdentification, &mOggPacketComment, &mOggPacketCodes); if (ErrorCheck(vahCode) == true) { //Error Write("vorbis_analysis_init error"); return; } if (ErrorCheck(vorbis_block_init(&mVorbisDspState, &mVorbisBlock)) == true) { //Error Write("vorbis_block_init error"); return; } }
//________________________________________________ // Init lame encoder // frequence : Impose frequency , 0 means reuse the incoming fq // mode : ADM_STEREO etc... // bitrate : Bitrate in kbps (96,192...) // return 0 : init failed // 1 : init succeeded //_______________________________________________ uint8_t AUDMEncoder_Vorbis::init(ADM_audioEncoderDescriptor *config) { int ret; VORBIS_encoderParam *vorbisConf=(VORBIS_encoderParam *)config->param; ADM_assert(config->paramSize==sizeof(VORBIS_encoderParam)); ogg_packet header1,header2,header3; int err; vorbis_info_init(&VI) ; switch(vorbisConf->mode) { case ADM_VORBIS_VBR: err=vorbis_encode_init(&VI, _wavheader->channels, _wavheader->frequency, -1, // Max bitrate config->bitrate*1000, //long nominal_bitrate, -1 //long min_bitrate)) ); break; case ADM_VORBIS_QUALITY : err=vorbis_encode_init_vbr(&VI, _wavheader->channels, _wavheader->frequency, vorbisConf->quality/10 ); break; default: ADM_assert(0); } if (err!=0) { delete (vorbisStruct*)_handle; _handle = NULL; printf("[vorbis] init error %d\n",err); return 0; } vorbis_analysis_init(&VD, &VI) ; vorbis_block_init(&VD, &VB); vorbis_comment_init(&VC); vorbis_comment_add_tag(&VC, "encoder", "AVIDEMUX2") ; vorbis_analysis_headerout(&VD, &VC, &header1, &header2, &header3); // Store all headers as extra data // see ogg vorbis decode for details // we need 3 packets _extraSize=header1.bytes+header2.bytes+header3.bytes+3*sizeof(uint32_t); _extraData=new uint8_t[_extraSize]; uint32_t *ex=(uint32_t *)_extraData; uint8_t *d; d=_extraData+sizeof(uint32_t)*3; ex[0]=header1.bytes; ex[1]=header2.bytes; ex[2]=header3.bytes; memcpy(d,header1.packet,ex[0]); d+=ex[0]; memcpy(d,header2.packet,ex[1]); d+=ex[1]; memcpy(d,header3.packet,ex[2]); vorbis_comment_clear(&VC); printf("\n[Vorbis]Vorbis encoder initialized\n"); switch(vorbisConf->mode) { case ADM_VORBIS_VBR: printf("[Vorbis]CBR Bitrate:%lu\n",config->bitrate); break; case ADM_VORBIS_QUALITY: //FIXME FIXME FIXME printf("[Vorbis]VBR Quality:%.1f\n",vorbisConf->quality); break; default: ADM_assert(0); } printf("[Vorbis]Channels :%lu\n",_wavheader->channels); printf("[Vorbis]Frequency :%lu\n",_wavheader->frequency); return 1; }
static LONG APIENTRY IOProc_Entry2(PVOID pmmioStr, USHORT usMsg, LONG lParam1, LONG lParam2) { PMMIOINFO pmmioinfo = (PMMIOINFO)pmmioStr; switch (usMsg) { case MMIOM_OPEN: { HMMIO hmmioSS; MMIOINFO mmioinfoSS; PSZ pszFileName = (char *)lParam1; if (!pmmioinfo) return MMIO_ERROR; if ((pmmioinfo->ulFlags & MMIO_READWRITE)) { #ifdef DEBUG fprintf(file,"ReadWrite - requested.\n"); #endif return MMIO_ERROR; } if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return MMIO_ERROR; if (!pmmioinfo->fccChildIOProc) { FOURCC fccFileStorageSystem; if (pmmioinfo->ulFlags & MMIO_CREATE) { if (mmioDetermineSSIOProc(pszFileName, pmmioinfo, &fccFileStorageSystem, NULL)) { fccFileStorageSystem = FOURCC_DOS; } } else { if (mmioIdentifyStorageSystem(pszFileName, pmmioinfo, &fccFileStorageSystem)) { return MMIO_ERROR; } } if (!fccFileStorageSystem) { return MMIO_ERROR; } else { pmmioinfo->fccChildIOProc = fccFileStorageSystem; } /* endif */ } memmove(&mmioinfoSS, pmmioinfo, sizeof(MMIOINFO)); mmioinfoSS.pIOProc = NULL; mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc; mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY; hmmioSS = mmioOpen (pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags); if (pmmioinfo->ulFlags & MMIO_DELETE) { if (!hmmioSS) { pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED; return MMIO_ERROR; } else return MMIO_SUCCESS; } if (!hmmioSS) return MMIO_ERROR; if (pmmioinfo->ulFlags & MMIO_READ) { DecInfo *decInfo = (DecInfo *)malloc(sizeof(DecInfo)); #ifdef DEBUG fprintf(file,"File Read: %s\n",pszFileName); #endif if (!decInfo) { mmioClose(hmmioSS, 0); return MMIO_ERROR; } decInfo->t = READNUM; decInfo->vorbisOptions = pmmioinfo->pExtraInfoStruct; pmmioinfo->pExtraInfoStruct = (PVOID)decInfo; { ov_callbacks cb; cb.read_func = mread; cb.seek_func = mseek; cb.close_func = mclose; cb.tell_func = mtell; if(0 != ov_open_callbacks((void *)hmmioSS, &decInfo->oggfile, 0, 0, cb)) { free(decInfo); mmioClose(hmmioSS, 0); return MMIO_ERROR; } } #ifdef DEBUG fprintf(file,"Open successfull\n"); #endif return MMIO_SUCCESS; } else if (pmmioinfo->ulFlags & MMIO_WRITE) { EncInfo *encInfo = (EncInfo *)malloc(sizeof(EncInfo)); #ifdef DEBUG fprintf(file,"File Write: %s\n",pszFileName); #endif if (!encInfo) { mmioClose(hmmioSS, 0); return MMIO_ERROR; } memset(encInfo, 0, sizeof(EncInfo)); encInfo->t = WRITENUM; encInfo->hmmioSS = hmmioSS; encInfo->vorbisOptions = (PVORBISOPTIONS)pmmioinfo->pExtraInfoStruct; pmmioinfo->pExtraInfoStruct = (PVOID)encInfo; return MMIO_SUCCESS; } #ifdef DEBUG fprintf(file,"File not read nor write: %s\n",pszFileName); #endif return MMIO_ERROR; } break; case MMIOM_READ: { if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct || !lParam1) return MMIO_ERROR; if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) { return MMIO_ERROR; // return mmioRead (ogginfo->hmmioSS, (PVOID) lParam1, (ULONG) lParam2); } else { OggVorbis_File *oggfile; long rc = 0; int current_section; long total = 0; oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile; if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR; while (lParam2 > 0) { rc = ov_read(oggfile, (char *)lParam1, (int)lParam2, 0, 2, 1, ¤t_section); if (rc < 0) { #ifdef DEBUG fprintf(file, "Read failed once\n"); #endif continue; } if (rc <= 0) break; lParam2 -= rc; lParam1 += rc; total += rc; } #ifdef DEBUG fprintf(file,"Read rc:%ld total:%ld\n",rc,total); #endif if (rc < 0) return MMIO_ERROR; return total; } } break; case MMIOM_SEEK: { LONG lPosDesired; OggVorbis_File *oggfile; vorbis_info *vi; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR; if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) return MMIO_ERROR; oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile; if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR; vi = ov_info(oggfile, -1); if (!vi) return MMIO_ERROR; if (SEEK_SET == lParam2) { lPosDesired = lParam1/(2*vi->channels); } else if (SEEK_CUR == lParam2) { if (0 == lParam1) { return ov_pcm_tell(oggfile)*2*vi->channels; } /* endif */ lPosDesired = ov_pcm_tell(oggfile) + lParam1/(2*vi->channels); } else if (SEEK_END == lParam2) { lPosDesired = ov_pcm_total(oggfile,-1) + lParam1/(2*vi->channels); } else { return MMIO_ERROR; } #ifdef DEBUG fprintf(file,"Seek to %ld by %d\n",lPosDesired, lParam2); #endif if (ov_pcm_seek(oggfile, lPosDesired) < 0) return MMIO_ERROR; return lPosDesired*2*vi->channels; } break; case MMIOM_CLOSE: { int rc; #ifdef DEBUG fprintf(file,"start CLOSE\n"); #endif if (!pmmioinfo) return MMIO_ERROR; if (pmmioinfo->pExtraInfoStruct) { DecInfo *decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct; #ifdef DEBUG fprintf(file,"ready CLOSE\n"); #endif if (READNUM == decInfo->t) { #ifdef DEBUG fprintf(file,"read CLOSE\n"); #endif ov_clear(&decInfo->oggfile); free(decInfo); decInfo = 0; rc=MMIO_SUCCESS; } else if (WRITENUM == decInfo->t) { EncInfo *encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct; #ifdef DEBUG fprintf(file,"write CLOSE\n"); #endif if (encInfo->headerSet) { vorbis_analysis_wrote(&encInfo->vd,0); rc = oggWrite(encInfo,1); ogg_stream_clear(&encInfo->os); vorbis_block_clear(&encInfo->vb); vorbis_dsp_clear(&encInfo->vd); vorbis_comment_clear(&encInfo->vc); vorbis_info_clear(&encInfo->vi); } mmioClose(encInfo->hmmioSS, 0); free(encInfo); encInfo = 0; rc = MMIO_SUCCESS; } else rc = MMIO_ERROR; pmmioinfo->pExtraInfoStruct = 0; #ifdef DEBUG fprintf(file,"CLOSE\n"); #endif return rc; } return MMIO_ERROR; } break; case MMIOM_IDENTIFYFILE: { unsigned char buf[4]; HMMIO hmmioTemp; ULONG ulTempFlags = MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY; LONG rc = MMIO_ERROR; if (!lParam1 && !lParam2) return MMIO_ERROR; hmmioTemp = (HMMIO)lParam2; if (!hmmioTemp) { hmmioTemp = mmioOpen((PSZ)lParam1, NULL, ulTempFlags); } if (hmmioTemp) { rc = mmioRead(hmmioTemp, buf, 4); if (rc == 4 && buf[0] == 'O' && buf[1] == 'g' && buf[2] == 'g' && buf[3] == 'S') { rc = MMIO_SUCCESS; } if (!lParam2) mmioClose(hmmioTemp, 0); } return rc; } break; case MMIOM_GETFORMATINFO: { PMMFORMATINFO pmmformatinfo; pmmformatinfo = (PMMFORMATINFO)lParam1; pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO); pmmformatinfo->fccIOProc = FOURCC_Vorbis; pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT; pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_AUDIO; pmmformatinfo->ulFlags = MMIO_CANREADTRANSLATED | MMIO_CANWRITETRANSLATED | MMIO_CANSEEKTRANSLATED; strcpy(pmmformatinfo->szDefaultFormatExt, "OGG"); pmmformatinfo->ulCodePage = 0; pmmformatinfo->ulLanguage = 0; pmmformatinfo->lNameLength = 21; return MMIO_SUCCESS; } break; case MMIOM_GETFORMATNAME: if (lParam2 > 21) { strcpy((PSZ)lParam1, "Ogg Vorbis"); return MMIO_SUCCESS; } else return MMIO_ERROR; break; case MMIOM_QUERYHEADERLENGTH: return (sizeof (MMAUDIOHEADER)); break; case MMIOM_GETHEADER: { OggVorbis_File *oggfile; DecInfo *decInfo; PMMAUDIOHEADER mmaudioheader; vorbis_info *vi; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0; if (!(pmmioinfo->ulFlags & MMIO_READ)) return 0; decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct; oggfile = &decInfo->oggfile; if (READNUM != decInfo->t){ pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE; return 0; } #ifdef DEBUG fprintf(file,"HERE\n"); #endif if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return 0; mmaudioheader = (MMAUDIOHEADER *)lParam1; if (sizeof(MMAUDIOHEADER) > lParam2) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH; return 0; } #ifdef DEBUG fprintf(file,"THERE\n"); #endif vi = ov_info(oggfile, -1); if (!vi) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE; return 0; } mmaudioheader->ulContentType = MMIO_MIDI_UNKNOWN; mmaudioheader->ulMediaType = MMIO_MEDIATYPE_AUDIO; mmaudioheader->mmXWAVHeader.WAVEHeader.usFormatTag=DATATYPE_WAVEFORM; mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels = vi->channels; mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec = vi->rate; mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample = 16; mmaudioheader->mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec= mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec * mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8; mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign= mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8; mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS= (unsigned long)(ov_time_total(oggfile, -1)*1000.0); mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes= (unsigned long)ov_pcm_total(oggfile, -1)* mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign; #ifdef DEBUG fprintf(file,"time: %ld size: %ld rate: %ld\n", mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS, mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec); #endif if (0 != decInfo->vorbisOptions && VORBIS_COOKIE == decInfo->vorbisOptions->cookie) { decInfo->vorbisOptions->nominal_bitrate = ov_bitrate(oggfile, -1); mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation = decInfo->vorbisOptions; } return (sizeof (MMAUDIOHEADER)); } break; case MMIOM_SETHEADER: { EncInfo *encInfo; PMMAUDIOHEADER mmaudioheader; int totalout = 0; int rc; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0; encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct; if (WRITENUM != encInfo->t) return 0; #ifdef DEBUG fprintf(file,"write header: %x, %x, %x\n",!(pmmioinfo->ulFlags & MMIO_WRITE), encInfo->headerSet, (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))); fprintf(file,"flag: %x, trans: %x\n",pmmioinfo->ulFlags,pmmioinfo->ulTranslate); #endif if (/*!(pmmioinfo->ulFlags & MMIO_WRITE) ||*/ encInfo->headerSet || (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))) return 0; if (!lParam1) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE; return 0; } mmaudioheader = (PMMAUDIOHEADER)lParam1; if (lParam2 != sizeof(MMAUDIOHEADER)) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH; return 0; } /********** Encode setup ************/ if (0 != mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample%8) { /* Bit-rate must be multiple of 8 */ return 0; } encInfo->bitsPerSample=mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample; #ifdef DEBUG fprintf(file,"ready to write header: "); #endif vorbis_info_init(&encInfo->vi); if (0 == encInfo->vorbisOptions || VORBIS_COOKIE != encInfo->vorbisOptions->cookie) { #ifdef DEBUG fprintf(file,"default quality 0.3\n"); #endif rc = vorbis_encode_init_vbr(&encInfo->vi, mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, 0.3); } else { #ifdef DEBUG fprintf(file,"bitsPerSample: %d channels: %d samplesPerSec: %ld min: %ld nominal: %ld max: %ld\n", encInfo->bitsPerSample, mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, encInfo->vorbisOptions->max_bitrate, encInfo->vorbisOptions->nominal_bitrate, encInfo->vorbisOptions->min_bitrate); #endif rc = vorbis_encode_init(&encInfo->vi, mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, encInfo->vorbisOptions->max_bitrate, encInfo->vorbisOptions->nominal_bitrate, encInfo->vorbisOptions->min_bitrate); } if (rc) { #ifdef DEBUG fprintf(file,"encodeInit failed: %d\n",rc); #endif return 0; } /* endif */ /* add a comment */ vorbis_comment_init(&encInfo->vc); vorbis_comment_add_tag(&encInfo->vc,"ENCODER","mmioVorbis"); /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init(&encInfo->vd,&encInfo->vi); vorbis_block_init(&encInfo->vd,&encInfo->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(&encInfo->os,rand()); { ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&encInfo->vd,&encInfo->vc,&header,&header_comm,&header_code); ogg_stream_packetin(&encInfo->os,&header); /* automatically placed in its own page */ ogg_stream_packetin(&encInfo->os,&header_comm); ogg_stream_packetin(&encInfo->os,&header_code); while(1){ int result=ogg_stream_flush(&encInfo->os,&encInfo->og); if(result==0)break; result = mmioWrite(encInfo->hmmioSS, encInfo->og.header,encInfo->og.header_len); totalout += result; if (result!=encInfo->og.header_len) { ogg_stream_clear(&encInfo->os); vorbis_block_clear(&encInfo->vb); vorbis_dsp_clear(&encInfo->vd); vorbis_comment_clear(&encInfo->vc); vorbis_info_clear(&encInfo->vi); return 0; } result = mmioWrite(encInfo->hmmioSS, encInfo->og.body,encInfo->og.body_len); totalout += result; if (result!=encInfo->og.body_len) { ogg_stream_clear(&encInfo->os); vorbis_block_clear(&encInfo->vb); vorbis_dsp_clear(&encInfo->vd); vorbis_comment_clear(&encInfo->vc); vorbis_info_clear(&encInfo->vi); return 0; } } } encInfo->headerSet = 1; return totalout; } break; case MMIOM_WRITE: { EncInfo *encInfo; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR; encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct; if (WRITENUM != encInfo->t) return MMIO_ERROR; if (!encInfo->headerSet) return MMIO_ERROR; if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) { if (!lParam1) return MMIO_ERROR; return mmioWrite(encInfo->hmmioSS, (PVOID)lParam1, lParam2); } else { if (lParam2 == 0) { vorbis_analysis_wrote(&encInfo->vd,0); } else { long i; int j, k; int num; float denom = 1; signed char *readbuffer = (char *)lParam1; /* data to encode */ /* expose the buffer to submit data */ int sampleSize = encInfo->vi.channels*encInfo->bitsPerSample/8; int samples = lParam2/sampleSize; float **buffer=vorbis_analysis_buffer(&encInfo->vd, samples); #ifdef DEBUG fprintf(file,"write: %ld\n",lParam2); #endif /* :TODO: Work with buffers not a multiple of sampleSize*/ if (lParam2 % sampleSize != 0) { #ifdef DEBUG fprintf(file,"Bad Write Buffer Size\n"); #endif return MMIO_ERROR; } for(i=0;i<samples;i++){ for (j=0;j<encInfo->vi.channels;j++) { num=0; denom=0.5; if (encInfo->bitsPerSample<=8) { buffer[j][i]=(float)((unsigned char)(readbuffer[i*sampleSize])- (1<<(encInfo->bitsPerSample-1)))/ (float)(1<<(encInfo->bitsPerSample-1)); } else { for (k=encInfo->bitsPerSample/8;k>0;k--) { if (k==encInfo->bitsPerSample/8) { num=(readbuffer[i*sampleSize+k-1]); } else { num=(num<<8)|((0xff)&(int)(readbuffer[i*sampleSize+k-1])); } denom *= 256.0; } buffer[j][i]=((float)num)/denom; } } /* endfor */ } vorbis_analysis_wrote(&encInfo->vd,i); } /* endif */ if (oggWrite(encInfo,0)>=0) { return lParam2; } else { return MMIO_ERROR; } /* endif */ } } break; #ifdef DEBUG case MMIOM_TEMPCHANGE: { return MMIO_SUCCESS; } break; #endif } #ifdef DEBUG fprintf(file,"unexpected command: %x\n",usMsg); #endif return MMIOERR_UNSUPPORTED_MESSAGE; }
//________________________________________________ // Init Vorbis encoder // frequence : Impose frequency , 0 means reuse the incoming fq // mode : VBR CBR // bitrate for CBR : bitrate in kbps (96,192...) // for VBR : quality (0, 1, 2, ... 11) // // return 0 : init failed // 1 : init succeeded //_______________________________________________ uint8_t AVDMProcessAudio_Vorbis::init( uint32_t bitrate, uint8_t mode) { ogg_packet header1,header2,header3; int err; vorbis_info_init(&VI) ; if (mode==0) { //VBR err=vorbis_encode_init_vbr(&VI, _wavheader->channels, _wavheader->frequency, ((float)bitrate-1)/10 ); } else { //CBR err=vorbis_encode_init(&VI, _wavheader->channels, _wavheader->frequency, -1, // Max bitrate bitrate*1000, //long nominal_bitrate, -1 //long min_bitrate)) ); } if (err!=0) { printf("vorbis init error\n"); return 0; } vorbis_analysis_init(&VD, &VI) ; vorbis_block_init(&VD, &VB); vorbis_comment_init(&VC); vorbis_comment_add_tag(&VC, "encoder", "AVIDEMUX2") ; vorbis_analysis_headerout(&VD, &VC, &header1, &header2, &header3); // Store all headers as extra data // see ogg vorbis decode for details // we need 3 packets _extraLen=header1.bytes+header2.bytes+header3.bytes+3*sizeof(uint32_t); _extraData=new uint8_t[_extraLen]; uint32_t *ex=(uint32_t *)_extraData; uint8_t *d; d=_extraData+sizeof(uint32_t)*3; ex[0]=header1.bytes; ex[1]=header2.bytes; ex[2]=header3.bytes; memcpy(d,header1.packet,ex[0]); d+=ex[0]; memcpy(d,header2.packet,ex[1]); d+=ex[1]; memcpy(d,header3.packet,ex[2]); vorbis_comment_clear(&VC); printf("\nVorbis encoder initialized\n"); if (mode==0) printf("VBR Quality:%i\n",bitrate-1); else printf("CBR Bitrate:%lu\n",bitrate); printf("Channels:%lu\n",_wavheader->channels); printf("Frequenc:%lu\n",_wavheader->frequency); return 1; }
static int icecast_internal_connect(t_channel *c, t_channel_outputstream *os, t_icecast *icecast, char *error, int errsize) { ogg_packet header; ogg_packet header_comm; ogg_packet header_code; (void)c; (void)os; if (icecast->connected) return MSERV_SUCCESS; if (shout_open(icecast->shout) != SHOUTERR_SUCCESS) { snprintf(error, errsize, "icecast: failed opening connection: %s", shout_get_error(icecast->shout)); goto failed; } mserv_log("Successfully connected to Icecast server '%s:%d'" " for mount '%s'", shout_get_host(icecast->shout), shout_get_port(icecast->shout), shout_get_mount(icecast->shout)); icecast->connected = 1; vorbis_info_init(&icecast->vi); if (vorbis_encode_init(&icecast->vi, os->channels, os->samplerate, -1, icecast->bitrate, -1) != 0) { snprintf(error, errsize, "icecast: failed to initialise vorbis engine"); goto failed; } vorbis_comment_init(&icecast->vc); vorbis_comment_add_tag(&icecast->vc, "ENCODER", "mserv " VERSION); vorbis_analysis_init(&icecast->vd, &icecast->vi); vorbis_block_init(&icecast->vd, &icecast->vb); ogg_stream_init(&icecast->os, rand()); vorbis_analysis_headerout(&icecast->vd, &icecast->vc, &header, &header_comm, &header_code); ogg_stream_packetin(&icecast->os, &header); ogg_stream_packetin(&icecast->os, &header_comm); ogg_stream_packetin(&icecast->os, &header_code); for (;;) { if (ogg_stream_flush(&icecast->os, &icecast->og) == 0) break; if (shout_send(icecast->shout, icecast->og.header, icecast->og.header_len) != SHOUTERR_SUCCESS || shout_send(icecast->shout, icecast->og.body, icecast->og.body_len) != SHOUTERR_SUCCESS) { snprintf(error, errsize, "icecast: failed to send starter to " "shout: %s", shout_get_error(icecast->shout)); vorbis_block_clear(&icecast->vb); vorbis_dsp_clear(&icecast->vd); vorbis_info_clear(&icecast->vi); goto failed; } } return MSERV_SUCCESS; failed: if (icecast->connected) shout_close(icecast->shout); icecast->connected = 0; return MSERV_FAILURE; }
//Method to start encoding int startEncoding(JNIEnv *env, jclass *cls_ptr, jlong *sampleRate_ptr, jlong *channels_ptr, jfloat *quality_ptr, jlong *bitrate_ptr, jobject *encoderDataFeed_ptr, int type) { //Dereference our variables jclass cls = (*cls_ptr); jlong sampleRate = (*sampleRate_ptr); jlong channels = (*channels_ptr); jfloat quality = (*quality_ptr); jlong bitrate = (*bitrate_ptr); jobject encoderDataFeed = (*encoderDataFeed_ptr); //Create our PCM data buffer signed char readbuffer[READ*4+44]; //Create a new java byte array to pass to the data feed method jbyteArray jByteArrayBuffer = (*env)->NewByteArray(env, READ*4); //Create a new java byte buffer to write to jbyteArray jByteArrayWriteBuffer = (*env)->NewByteArray(env, READ*8); //Find our java classes we'll be calling jclass encoderDataFeedClass = (*env)->FindClass(env, "org/xiph/vorbis/encoder/EncodeFeed"); //Find our java method id's we'll be calling jmethodID writeVorbisDataMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "writeVorbisData", "([BI)I"); jmethodID readPCMDataMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "readPCMData", "([BI)J"); jmethodID startMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "start", "()V"); jmethodID stopMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "stop", "()V"); 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; /********** Encode setup ************/ __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Setting up encoding"); 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)); *********************************************************************/ switch(type) { case WITH_BITRATE: __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Initializing with %lld channels %lldHz sample rate and %lld bitrate", channels, sampleRate, bitrate); ret=vorbis_encode_init(&vi, (long)channels, (long)sampleRate, (long)-1, (long)bitrate, (long)-1); break; case WITH_QUALITY: __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Initializing with %lld channels %lldHz sample rate and %f quality", channels, sampleRate, quality); ret=vorbis_encode_init_vbr(&vi, (long)channels, (long)sampleRate, (float)quality); break; default: __android_log_print(ANDROID_LOG_ERROR, "VorbisEncoder", "Failed to initialize"); stopEncodeFeed(env, &encoderDataFeed, &stopMethodId); return ERROR_INITIALIZING; } /* 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) { __android_log_print(ANDROID_LOG_ERROR, "VorbisEncoder", "Failed to initialize"); stopEncodeFeed(env, &encoderDataFeed, &stopMethodId); return ERROR_INITIALIZING; } startEncodeFeed(env, &encoderDataFeed, &startMethodId); /* add a comment */ __android_log_print(ANDROID_LOG_DEBUG, "VorbisEncoder", "Adding comments"); vorbis_comment_init(&vc); vorbis_comment_add_tag(&vc,"ENCODER","JNIVorbisEncoder"); /* 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 */ __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Writting header"); while(!eos){ int result=ogg_stream_flush(&os,&og); if(result==0)break; writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer); writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer); } } __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Starting to read from pcm callback"); while(!eos){ long i; long bytes = readPCMDataFromEncoderDataFeed(env, &encoderDataFeed, &readPCMDataMethodId, readbuffer, READ*4, &jByteArrayBuffer); 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 */ __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "End of file"); vorbis_analysis_wrote(&vd,0); }else{ /* data to encode */ /* expose the buffer to submit data */ float **buffer=vorbis_analysis_buffer(&vd,bytes/(2*channels)); /* uninterleave samples */ int channel; for(i=0;i<bytes/(2*channels);i++) { for(channel = 0; channel < channels; channel++) { buffer[channel][i]=((readbuffer[i*(2*channels)+(channel*2+1)]<<8)| (0x00ff&(int)readbuffer[i*(2*channels)+(channel*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; writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer); writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer); /* 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 */ __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Cleaning up encoder"); 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 */ __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Completed encoding."); stopEncodeFeed(env, &encoderDataFeed, &stopMethodId); //Clean up encode buffers (*env)->DeleteLocalRef(env, jByteArrayBuffer); (*env)->DeleteLocalRef(env, jByteArrayWriteBuffer); return SUCCESS; }
// Just create the Quicktime objects since this routine is also called // for reopening. int FileVorbis::open_file(int rd, int wr) { int result = 0; this->rd = rd; this->wr = wr; //printf("FileVorbis::open_file 1\n"); if(rd) { //printf("FileVorbis::open_file 1\n"); if(!(fd = fopen(asset->path, "rb"))) { eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path); result = 1; } else { //printf("FileVorbis::open_file 2 %p %p\n", fd, vf); if(ov_open(fd, &vf, NULL, 0) < 0) { eprintf("Invalid bitstream in %s\n", asset->path); result = 1; } else { //printf("FileVorbis::open_file 1\n"); vorbis_info *vi = ov_info(&vf, -1); asset->channels = vi->channels; if(!asset->sample_rate) asset->sample_rate = vi->rate; //printf("FileVorbis::open_file 1\n"); asset->audio_length = ov_pcm_total(&vf,-1); //printf("FileVorbis::open_file 1\n"); asset->audio_data = 1; // printf("FileVorbis::open_file 1 %d %d %d\n", // asset->channels, // asset->sample_rate, // asset->audio_length); } } } if(wr) { if(!(fd = fopen(asset->path, "wb"))) { eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path); result = 1; } else { vorbis_info_init(&vi); if(!asset->vorbis_vbr) result = vorbis_encode_init(&vi, asset->channels, asset->sample_rate, asset->vorbis_max_bitrate, asset->vorbis_bitrate, asset->vorbis_min_bitrate); else { result = vorbis_encode_setup_managed(&vi, asset->channels, asset->sample_rate, asset->vorbis_max_bitrate, asset->vorbis_bitrate, asset->vorbis_min_bitrate); result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL); result |= vorbis_encode_setup_init(&vi); } if(!result) { vorbis_analysis_init(&vd, &vi); vorbis_block_init(&vd, &vb); vorbis_comment_init(&vc); srand(time(NULL)); ogg_stream_init(&os, rand()); 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); ogg_stream_packetin(&os, &header_comm); ogg_stream_packetin(&os, &header_code); while(1) { int result = ogg_stream_flush(&os, &og); if(result == 0) break; fwrite(og.header, 1, og.header_len, fd); fwrite(og.body, 1, og.body_len, fd); } } } } //printf("FileVorbis::open_file 2\n"); return result; }
bool Start(void *ctx, int iInChannels, int iInRate, int iInBits, const char* title, const char* artist, const char* albumartist, const char* album, const char* year, const char* track, const char* genre, const char* comment, int iTrackLength) { ogg_context *context = (ogg_context *)ctx; if (!context || !context->callbacks.write) return false; // we accept only 2 ch 16bit atm if (iInChannels != 2 || iInBits != 16) return false; if (preset == -1) vorbis_encode_init(&context->vorbisInfo, iInChannels, iInRate, -1, bitrate*1000, -1); else vorbis_encode_init_vbr(&context->vorbisInfo, iInChannels, iInRate, float(preset)/10.0f); /* add a comment */ vorbis_comment comm; vorbis_comment_init(&comm); vorbis_comment_add_tag(&comm, (char*)"comment", (char*)comment); vorbis_comment_add_tag(&comm, (char*)"artist", (char*)artist); vorbis_comment_add_tag(&comm, (char*)"title", (char*)title); vorbis_comment_add_tag(&comm, (char*)"album", (char*)album); vorbis_comment_add_tag(&comm, (char*)"albumartist", (char*)albumartist); vorbis_comment_add_tag(&comm, (char*)"genre", (char*)genre); vorbis_comment_add_tag(&comm, (char*)"tracknumber", (char*)track); vorbis_comment_add_tag(&comm, (char*)"date", (char*)year); /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init(&context->vorbisDspState, &context->vorbisInfo); vorbis_block_init(&context->vorbisDspState, &context->vorbisBlock); /* set up our packet->stream encoder */ /* pick a random serial number; that way we can more likely build chained streams just by concatenation */ srand((unsigned int)time(NULL)); ogg_stream_init(&context->oggStreamState, rand()); /* write out the metadata */ ogg_packet header; ogg_packet header_comm; ogg_packet header_code; ogg_page page; vorbis_analysis_headerout(&context->vorbisDspState, &comm, &header, &header_comm, &header_code); ogg_stream_packetin(&context->oggStreamState, &header); ogg_stream_packetin(&context->oggStreamState, &header_comm); ogg_stream_packetin(&context->oggStreamState, &header_code); while (1) { /* This ensures the actual * audio data will start on a new page, as per spec */ int result = ogg_stream_flush(&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); } vorbis_comment_clear(&comm); context->inited = true; return true; }
const char * _edje_multisense_encode_to_ogg_vorbis(char *snd_path, double quality, SF_INFO sfinfo) { 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; char *tmp; SNDFILE *sfile; FILE *fout; sfile = sf_open(snd_path, SFM_READ, &sfinfo); if (!sfile) return NULL; if (!sf_format_check(&sfinfo)) { sf_close(sfile); return NULL; } tmp = malloc(strlen(snd_path) + 1 + 4); if (!tmp) { sf_close(sfile); return NULL; } strcpy(tmp, snd_path); snd_path = tmp; strcat(snd_path, ".ogg"); fout = fopen(snd_path, "wb"); if (!fout) { free(snd_path); sf_close(sfile); return NULL; } /********** Encode setup ************/ vorbis_info_init(&vi); ret = vorbis_encode_init(&vi, sfinfo.channels, sfinfo.samplerate, -1, (long)(quality * 1000), -1); if (ret == OV_EFAULT) printf("OV_EFAULT\n"); if (ret == OV_EINVAL) printf("OV_EINVAL\n"); if (ret == OV_EIMPL) printf("OV_EIMPL\n"); if (ret) { fclose(fout); free(snd_path); sf_close(sfile); return NULL; } /* add a comment */ vorbis_comment_init(&vc); vorbis_comment_add_tag(&vc, "", ""); /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init(&vd, &vi); vorbis_block_init(&vd, &vb); srand(time(NULL)); ogg_stream_init(&os, rand()); 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); while (!eos) { int result = ogg_stream_flush(&os, &og); if (!result) break; fwrite(og.header, 1, og.header_len, fout); fwrite(og.body, 1, og.body_len, fout); } while (!eos) { int i, ch; float readbuffer[READBUF * 2]; sf_count_t count; count = sf_readf_float(sfile, readbuffer, READBUF); if (!count) vorbis_analysis_wrote(&vd, 0); else { float **buffer = vorbis_analysis_buffer(&vd, count); /* uninterleave samples */ for (i = 0; i < count; i++) { for (ch = 0; ch < sfinfo.channels; ch++) buffer[ch][i]= readbuffer[(i * sfinfo.channels) + ch]; } vorbis_analysis_wrote(&vd, 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) { int result = ogg_stream_pageout(&os, &og); if (!result) break; fwrite(og.header, 1, og.header_len, fout); fwrite(og.body, 1, og.body_len, fout); if (ogg_page_eos(&og)) eos = 1; } } } } ogg_stream_clear(&os); vorbis_block_clear(&vb); vorbis_dsp_clear(&vd); vorbis_comment_clear(&vc); vorbis_info_clear(&vi); sf_close(sfile); fclose (fout); return snd_path; }
gboolean ucil_theora_combine_av_file( const char *path, const char *codec, gboolean remove, ucil_processing_info_func_t procfunc, void *func_data, GError **error ) { FILE *f; FILE *af; FILE *vf; gchar *apath; gchar *vpath; long len; long filepos = 0; ogg_sync_state oy; ogg_stream_state tins; theora_comment tc; theora_info ti; theora_state ts; ogg_stream_state vs; vorbis_info vi; vorbis_comment vc; vorbis_dsp_state vd; vorbis_block vb; ogg_page og; ogg_packet op; ogg_packet header_comm; ogg_packet header_code; int pkt; double videopos, audiopos; f = fopen( path, "w" ); if( !f ) { gchar *name = g_filename_display_name( path ); g_set_error( error, G_FILE_ERROR, g_file_error_from_errno( errno ), _("Could not open '%s' for writing: %s"), name, g_strerror( errno ) ); g_free( name ); return FALSE; } apath = g_strconcat( path, ".atmp", NULL ); af = fopen( apath, "r" ); if( !af ) { gchar *name = g_filename_display_name( apath ); g_set_error( error, G_FILE_ERROR, g_file_error_from_errno( errno ), _("Could not open '%s' for reading: %s"), name, g_strerror( errno ) ); g_free( name ); g_free( apath ); fclose( f ); return FALSE; } vpath = g_strconcat( path, ".vtmp", NULL ); vf = fopen( vpath, "r" ); if( !vf ) { gchar *name = g_filename_display_name( vpath ); g_set_error( error, G_FILE_ERROR, g_file_error_from_errno( errno ), _("Could not open '%s' for reading: %s"), name, g_strerror( errno ) ); g_free( name ); g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); return FALSE; } fseek( af, 0L, SEEK_END ); len = ftell( af ); fseek( af, 0L, SEEK_SET ); ogg_sync_init( &oy ); theora_comment_init( &tc ); theora_info_init( &ti ); if( ogg_stream_init( &vs, 2 ) != 0 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Failed to initialize audio stream") ); return FALSE; } vorbis_info_init( &vi ); if( vorbis_encode_init( &vi, 2, 44100, -1, 128000, -1 ) ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Failed to initialize audio encoder") ); return FALSE; } vorbis_comment_init( &vc ); vorbis_analysis_init( &vd, &vi ); vorbis_block_init( &vd, &vb ); // // write theora header page // { ogg_page og; while( ogg_sync_pageout( &oy, &og ) == 0 ) { int bytes; bytes = buffer_data( vf, &oy ); if( bytes == 0 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Invalid video stream") ); return FALSE; } } if( !ogg_page_bos( &og ) ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Invalid video stream") ); return FALSE; } ogg_stream_init( &tins, ogg_page_serialno( &og ) ); fwrite( og.header, 1, og.header_len, f ); fwrite( og.body, 1, og.body_len, f ); if( ogg_stream_pagein( &tins, &og ) < 0 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Invalid video stream") ); return FALSE; } pkt = 0; while( ( pkt < 3 ) && ( ogg_stream_packetout( &tins, &op ) > 0 ) ) { if( theora_decode_header( &ti, &tc, &op ) != 0 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Invalid video stream") ); return FALSE; } pkt++; } } // // Write vorbis header page // vorbis_analysis_headerout( &vd, &vc, &op, &header_comm, &header_code ); ogg_stream_packetin( &vs, &op ); if( ogg_stream_pageout( &vs, &og ) != 1 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Could not create audio stream") ); return FALSE; } fwrite( og.header, 1, og.header_len, f ); fwrite( og.body, 1, og.body_len, f ); ogg_stream_packetin( &vs, &header_comm ); ogg_stream_packetin( &vs, &header_code ); // write remaining theora headers for( pkt = 1; pkt < 3; ) { ogg_page og; if( ogg_sync_pageout( &oy, &og ) > 0 ) { fwrite( og.header, 1, og.header_len, f ); fwrite( og.body, 1, og.body_len, f ); if( ogg_stream_pagein( &tins, &og ) < 0 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Invalid video stream") ); return FALSE; } while( ( pkt < 3 ) && ( ogg_stream_packetout( &tins, &op ) > 0 ) ) { if( theora_decode_header( &ti, &tc, &op ) != 0 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Invalid video stream") ); return FALSE; } pkt++; } } else { int bytes; bytes = buffer_data( vf, &oy ); if( bytes == 0 ) { g_free( apath ); g_free( vpath ); fclose( f ); fclose( af ); fclose( vf ); g_set_error( error, UCIL_ERROR, UCIL_ERROR_INVALID_STREAM, _("Invalid video stream") ); return FALSE; } } } theora_decode_init( &ts, &ti ); // // Write remaining vorbis headers // while( ogg_stream_flush( &vs, &og ) > 0 ) { fwrite( og.header, 1, og.header_len, f ); fwrite( og.body, 1, og.body_len, f ); } audiopos = 0.0; videopos = 0.0; while( !feof( af ) ) { signed char abuf[512 * 4]; int n_samples; if( feof( vf ) || ( audiopos <= videopos ) ) { n_samples = fread( abuf, 4, 512, af ); audiopos = encode_vorbis( f, &vd, &vs, &vb, 44100, audiopos, abuf, n_samples ); filepos += n_samples * 4; } else { buffer_data( vf, &oy ); if( ogg_sync_pageout( &oy, &og ) > 0 ) { double tmppos; fwrite( og.header, 1, og.header_len, f ); fwrite( og.body, 1, og.body_len, f ); if( ogg_stream_pagein( &tins, &og ) < 0 ) { TRACE( "failed to decode theora\n" ); } ogg_stream_packetout( &tins, &op ); tmppos = theora_granule_time( &ts, ogg_page_granulepos( &og ) ); if( tmppos > 0 ) { videopos = tmppos; } } } if( procfunc ) { procfunc( func_data, (double)filepos/(double)len ); } } while( !feof( vf ) && buffer_data( vf, &oy ) ) { if( ogg_sync_pageout( &oy, &og ) > 0 ) { fwrite( og.header, 1, og.header_len, f ); fwrite( og.body, 1, og.body_len, f ); } } if( remove ) { unlink( vpath ); unlink( apath ); } g_free( vpath ); g_free( apath ); fclose( f ); fclose( af ); fclose( vf ); return TRUE; }
static int encode(quicktime_t *file, int16_t **input_i, float **input_f, int track, long samples) { int result = 0; int64_t offset = quicktime_position(file); quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_trak_t *trak = track_map->track; quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; int samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate; float **output; int size = 0; int chunk_started = 0; quicktime_atom_t chunk_atom; if(samplerate < 32000) { printf("encode: sample rate %d not supported.\n", samplerate); return 1; } if(!codec->encode_initialized) { ogg_packet header; ogg_packet header_comm; ogg_packet header_code; codec->encode_initialized = 1; if(file->use_avi) trak->mdia.minf.stbl.stsd.table[0].sample_size = 0; vorbis_info_init(&codec->enc_vi); if(codec->use_vbr) { result = vorbis_encode_setup_managed(&codec->enc_vi, track_map->channels, samplerate, codec->max_bitrate, codec->nominal_bitrate, codec->min_bitrate); result |= vorbis_encode_ctl(&codec->enc_vi, OV_ECTL_RATEMANAGE_AVG, NULL); result |= vorbis_encode_setup_init(&codec->enc_vi); } else { vorbis_encode_init(&codec->enc_vi, track_map->channels, samplerate, codec->max_bitrate, codec->nominal_bitrate, codec->min_bitrate); } vorbis_comment_init(&codec->enc_vc); vorbis_analysis_init(&codec->enc_vd, &codec->enc_vi); vorbis_block_init(&codec->enc_vd, &codec->enc_vb); srand(time(NULL)); ogg_stream_init(&codec->enc_os, rand()); vorbis_analysis_headerout(&codec->enc_vd, &codec->enc_vc, &header, &header_comm, &header_code); ogg_stream_packetin(&codec->enc_os, &header); ogg_stream_packetin(&codec->enc_os, &header_comm); ogg_stream_packetin(&codec->enc_os, &header_code); FLUSH_OGG1 }
/*------------------------------------------------------------------------------ * Open an encoding session *----------------------------------------------------------------------------*/ bool VorbisLibEncoder :: open ( void ) throw ( Exception ) { int ret; if ( isOpen() ) { close(); } vorbis_info_init( &vorbisInfo); switch ( getOutBitrateMode() ) { case cbr: ret = vorbis_encode_setup_managed( &vorbisInfo, getInChannel(), getOutSampleRate(), -1, getOutBitrate() * 1000, -1) || vorbis_encode_ctl( &vorbisInfo, OV_ECTL_RATEMANAGE_AVG, NULL) || vorbis_encode_setup_init( &vorbisInfo); if ( ret ) { throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); } break; case abr: if ( (ret = vorbis_encode_init( &vorbisInfo, getInChannel(), getOutSampleRate(), -1, getOutBitrate() * 1000, -1 )) ) { throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); } break; case vbr: if ( (ret = vorbis_encode_init_vbr( &vorbisInfo, getInChannel(), getOutSampleRate(), getOutQuality() )) ) { throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); } break; } if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) { throw Exception( __FILE__, __LINE__, "vorbis analysis init error", ret); } if ( (ret = vorbis_block_init( &vorbisDspState, &vorbisBlock)) ) { throw Exception( __FILE__, __LINE__, "vorbis block init error", ret); } if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) { throw Exception( __FILE__, __LINE__, "ogg stream init error", ret); } // open the underlying sink if ( !sink->open() ) { throw Exception( __FILE__, __LINE__, "vorbis lib opening underlying sink error"); } // create an empty vorbis_comment structure vorbis_comment_init( &vorbisComment); // create the vorbis stream headers and send them to the underlying sink ogg_packet header; ogg_packet commentHeader; ogg_packet codeHeader; if ( (ret = vorbis_analysis_headerout( &vorbisDspState, &vorbisComment, &header, &commentHeader, &codeHeader )) ) { throw Exception( __FILE__, __LINE__, "vorbis header init error", ret); } ogg_stream_packetin( &oggStreamState, &header); ogg_stream_packetin( &oggStreamState, &commentHeader); ogg_stream_packetin( &oggStreamState, &codeHeader); ogg_page oggPage; while ( ogg_stream_flush( &oggStreamState, &oggPage) ) { sink->write( oggPage.header, oggPage.header_len); sink->write( oggPage.body, oggPage.body_len); } vorbis_comment_clear( &vorbisComment ); // initialize the resampling coverter if needed if ( converter ) { converter->initialize( resampleRatio, getInChannel()); } encoderOpen = true; return true; }
void* vorbisEncoder(void *obj) { VS::setThreadName("vorbisEncoder"); VorbisEncoderData* ved = (VorbisEncoderData*)obj; vorbis_info vi; vorbis_dsp_state vd; vorbis_block vb; vorbis_info_init(&vi); vorbis_encode_init(&vi, ved->m_channels, ved->m_sample_rate, -1, 112000, -1); vorbis_analysis_init(&vd, &vi); vorbis_block_init(&vd, &vb); vorbis_comment vc; vorbis_comment_init(&vc); vorbis_comment_add_tag(&vc, "ENCODER", "STK vorbis encoder"); ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code); if (header.bytes > 255 || header_comm.bytes > 255) { Log::error("vorbisEncoder", "Header is too long."); return NULL; } FILE* vb_data = fopen((getRecordingName() + ".audio").c_str(), "wb"); if (vb_data == NULL) { Log::error("vorbisEncoder", "Failed to open file for encoding" " vorbis."); return NULL; } fwrite(&ved->m_sample_rate, 1, sizeof(uint32_t), vb_data); fwrite(&ved->m_channels, 1, sizeof(uint32_t), vb_data); const uint32_t all = header.bytes + header_comm.bytes + header_code.bytes + 3; fwrite(&all, 1, sizeof(uint32_t), vb_data); uint8_t size = 2; fwrite(&size, 1, sizeof(uint8_t), vb_data); size = (uint8_t)header.bytes; fwrite(&size, 1, sizeof(uint8_t), vb_data); size = (uint8_t)header_comm.bytes; fwrite(&size, 1, sizeof(uint8_t), vb_data); fwrite(header.packet, 1, header.bytes, vb_data); fwrite(header_comm.packet, 1, header_comm.bytes, vb_data); fwrite(header_code.packet, 1, header_code.bytes, vb_data); Synchronised<std::list<int8_t*> >* audio_data = (Synchronised<std::list<int8_t*> >*)ved->m_data; pthread_cond_t* cond_request = ved->m_enc_request; ogg_packet op; int64_t last_timestamp = 0; bool eos = false; while (eos == false) { audio_data->lock(); bool waiting = audio_data->getData().empty(); while (waiting) { pthread_cond_wait(cond_request, audio_data->getMutex()); waiting = audio_data->getData().empty(); } int8_t* audio_buf = audio_data->getData().front(); audio_data->getData().pop_front(); audio_data->unlock(); if (audio_buf == NULL) { vorbis_analysis_wrote(&vd, 0); eos = true; } else { float **buffer = vorbis_analysis_buffer(&vd, 1024); const unsigned channels = ved->m_channels; if (ved->m_audio_type == VorbisEncoderData::AT_PCM) { for (unsigned j = 0; j < channels; j++) { for (unsigned i = 0; i < 1024; i++) { int8_t* each_channel = &audio_buf[i * channels * 2 + j * 2]; buffer[j][i] = float((each_channel[1] << 8) | (0x00ff & (int)each_channel[0])) / 32768.0f; } } } else { for (unsigned j = 0; j < channels; j++) { for (unsigned i = 0; i < 1024; i++) { float* fbuf = reinterpret_cast<float*>(audio_buf); buffer[j][i] = fbuf[i * channels + j]; } } } vorbis_analysis_wrote(&vd, 1024); } while (vorbis_analysis_blockout(&vd, &vb) == 1) { vorbis_analysis(&vb, NULL); vorbis_bitrate_addblock(&vb); while (vorbis_bitrate_flushpacket(&vd, &op)) { if (op.granulepos > 0) { uint32_t frame_size = (uint32_t)op.bytes; fwrite(&frame_size, 1, sizeof(uint32_t), vb_data); fwrite(&last_timestamp, 1, sizeof(int64_t), vb_data); fwrite(op.packet, 1, frame_size, vb_data); double s = (double)op.granulepos / (double)ved->m_sample_rate * 1000000000.; last_timestamp = (int64_t)s; } } } delete[] audio_buf; } vorbis_block_clear(&vb); vorbis_dsp_clear(&vd); vorbis_comment_clear(&vc); vorbis_info_clear(&vi); fclose(vb_data); return NULL; } // vorbisEncoder
int OggEncode( wsul nSize, wsfb *bData, wsul nCh, int nBit, wsf_file *wOut, wsul nFreq ) { 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 */ wsul nRLen; int eos=0,ret; nRLen = READ; if (nCh == 1) nRLen /= 2; if (nBit) nRLen /= 2; if (nFreq < 22050) nFreq = 44100; if (nFreq > 44800) nFreq = 44100; wsf_file *wIn; wIn = wsfopenmem(bData,nSize); /********** 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 qulity 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_RATEMANAGE_AVG,NULL) || vorbis_encode_setup_init(&vi)); *********************************************************************/ if (nFreq == 0) ret = vorbis_encode_init(&vi,2,44100,-1,g_nRate*1000,-1); else { ret = vorbis_encode_init(&vi,2,nFreq,-1,g_nRate*1000,-1); if (ret) { vorbis_info_clear(&vi); vorbis_info_init(&vi); ret = vorbis_encode_init(&vi,2,44100,-1,g_nRate*1000,-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)printf("Errorly, improper bitrate?\n\n"); if(ret)return 1; /* add a comment */ vorbis_comment_init(&vc); vorbis_comment_add_tag(&vc,"ENCODER","WSF Encoder"); /* 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; wsfwrite(og.header,og.header_len,wOut); wsfwrite(og.body,og.body_len,wOut); } } while(!eos) { int i; int bytes=wsfread(readbuffer,nRLen*4,wIn); /* 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,nRLen); /* uninterleave samples */ if (nBit == 16) { for(i=0; i<bytes/4; i++) { buffer[0][i]=((readbuffer[i*4+1]<<8)| (0x00ff&(int)readbuffer[i*4]))/32768.f; if (buffer[1]) buffer[1][i]=((readbuffer[i*4+3]<<8)| (0x00ff&(int)readbuffer[i*4+2]))/32768.f; } } else { for(i=0; i<bytes/2; i++) { buffer[0][i]=((readbuffer[i*2+1]<<8)| (0x00ff&(int)readbuffer[i*2]))/32768.f; if (buffer[1]) buffer[1][i]=((readbuffer[i*2+3]<<8)| (0x00ff&(int)readbuffer[i*2+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; wsfwrite(og.header,og.header_len,wOut); wsfwrite(og.body,og.body_len,wOut); /* 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); wsfclose(wIn); /* ogg_page and ogg_packet structs always point to storage in libvorbis. They're never freed or manipulated directly */ return(0); }
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; }
/*------------------------------------------------------------------------------ * Open an encoding session *----------------------------------------------------------------------------*/ bool VorbisLibEncoder :: open ( void ) throw ( Exception ) { int ret; if ( isOpen() ) { close(); } vorbis_info_init( &vorbisInfo); if ( isVBR() ) { if ( (ret = vorbis_encode_init_vbr( &vorbisInfo, getInChannel(), getOutSampleRate(), getOutQuality() )) ) { throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); } } else { #ifdef VORBIS_LIB_RC3 if ( (ret = vorbis_encode_init( &vorbisInfo, getInChannel(), getOutSampleRate(), getOutBitrate() * 1024, getOutBitrate() * 1024, -1 )) ) { throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); } #else if ( (ret = vorbis_encode_init( &vorbisInfo, getInChannel(), getOutSampleRate(), -1, getOutBitrate() * 1024, -1 )) ) { throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); } #endif } if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) { throw Exception( __FILE__, __LINE__, "vorbis analysis init error", ret); } if ( (ret = vorbis_block_init( &vorbisDspState, &vorbisBlock)) ) { throw Exception( __FILE__, __LINE__, "vorbis block init error", ret); } if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) { throw Exception( __FILE__, __LINE__, "ogg stream init error", ret); } // open the underlying sink if ( !sink->open() ) { throw Exception( __FILE__, __LINE__, "vorbis lib opening underlying sink error"); } // create an empty vorbis_comment structure vorbis_comment_init( &vorbisComment); // create the vorbis stream headers and send them to the underlying sink ogg_packet header; ogg_packet commentHeader; ogg_packet codeHeader; if ( (ret = vorbis_analysis_headerout( &vorbisDspState, &vorbisComment, &header, &commentHeader, &codeHeader )) ) { throw Exception( __FILE__, __LINE__, "vorbis header init error", ret); } ogg_stream_packetin( &oggStreamState, &header); ogg_stream_packetin( &oggStreamState, &commentHeader); ogg_stream_packetin( &oggStreamState, &codeHeader); ogg_page oggPage; while ( ogg_stream_flush( &oggStreamState, &oggPage) ) { sink->write( oggPage.header, oggPage.header_len); sink->write( oggPage.body, oggPage.body_len); } vorbis_comment_clear( &vorbisComment ); // initialize the resampling coverter if needed if ( converter ) { converter->initialize( resampleRatio, getInChannel()); } encoderOpen = true; return true; }
static int vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; int k, ret ; vorbis_info_init (&vdata->vinfo) ; /* The style of encoding should be selectable here, VBR quality mode. */ ret = vorbis_encode_init_vbr (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, vdata->quality) ; #if 0 ret = vorbis_encode_init (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) ; /* average bitrate mode */ ret = ( vorbis_encode_setup_managed (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) || vorbis_encode_ctl (&vdata->vinfo, OV_ECTL_RATEMANAGE_AVG, NULL) || vorbis_encode_setup_init (&vdata->vinfo) ) ; #endif if (ret) return SFE_BAD_OPEN_FORMAT ; vdata->loc = 0 ; /* add a comment */ vorbis_comment_init (&vdata->vcomment) ; vorbis_comment_add_tag (&vdata->vcomment, "ENCODER", "libsndfile") ; for (k = 0 ; k < SF_MAX_STRINGS ; k++) { const char * name ; if (psf->strings.data [k].type == 0) break ; switch (psf->strings.data [k].type) { case SF_STR_TITLE : name = "TITLE" ; break ; case SF_STR_COPYRIGHT : name = "COPYRIGHT" ; break ; case SF_STR_SOFTWARE : name = "SOFTWARE" ; break ; case SF_STR_ARTIST : name = "ARTIST" ; break ; case SF_STR_COMMENT : name = "COMMENT" ; break ; case SF_STR_DATE : name = "DATE" ; break ; case SF_STR_ALBUM : name = "ALBUM" ; break ; case SF_STR_LICENSE : name = "LICENSE" ; break ; case SF_STR_TRACKNUMBER : name = "Tracknumber" ; break ; case SF_STR_GENRE : name = "Genre" ; break ; default : continue ; } ; vorbis_comment_add_tag (&vdata->vcomment, name, psf->strings.storage + psf->strings.data [k].offset) ; } ; /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init (&vdata->vdsp, &vdata->vinfo) ; vorbis_block_init (&vdata->vdsp, &vdata->vblock) ; /* ** 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 (&odata->ostream, psf_rand_int32 ()) ; /* 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 ; int result ; vorbis_analysis_headerout (&vdata->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ; ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */ ogg_stream_packetin (&odata->ostream, &header_comm) ; ogg_stream_packetin (&odata->ostream, &header_code) ; /* This ensures the actual * audio data will start on a new page, as per spec */ while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0) { psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ; psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ; } ; } return 0 ; } /* vorbis_write_header */
int main(int argc,char *argv[]){ int c,long_option_index,ret; ogg_stream_state to; /* take physical pages, weld into a logical stream of packets */ ogg_stream_state vo; /* 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 */ theora_state td; theora_info ti; theora_comment tc; 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 audioflag=0; int videoflag=0; int akbps=0; int vkbps=0; ogg_int64_t audio_bytesout=0; ogg_int64_t video_bytesout=0; double timebase; FILE* outfile = stdout; #ifdef _WIN32 # ifdef THEORA_PERF_DATA LARGE_INTEGER start_time; LARGE_INTEGER final_time; LONGLONG elapsed_ticks; LARGE_INTEGER ticks_per_second; LONGLONG elapsed_secs; LONGLONG elapsed_sec_mod; double elapsed_secs_dbl ; # endif /* 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 while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){ switch(c){ case 'o': outfile=fopen(optarg,"wb"); if(outfile==NULL){ fprintf(stderr,"Unable to open output file '%s'\n", optarg); exit(1); } break;; case 'a': audio_q=atof(optarg)*.099; if(audio_q<-.1 || audio_q>1){ fprintf(stderr,"Illegal audio quality (choose -1 through 10)\n"); exit(1); } audio_r=-1; break; case 'v': video_q=rint(atof(optarg)*6.3); if(video_q<0 || video_q>63){ fprintf(stderr,"Illegal video quality (choose 0 through 10)\n"); exit(1); } video_r=0; break; case 'A': audio_r=atof(optarg)*1000; if(audio_q<0){ fprintf(stderr,"Illegal audio quality (choose > 0 please)\n"); exit(1); } audio_q=-99; break; case 'V': video_r=rint(atof(optarg)*1000); if(video_r<45000 || video_r>2000000){ fprintf(stderr,"Illegal video bitrate (choose 45kbps through 2000kbps)\n"); exit(1); } video_q=0; break; case 's': video_an=rint(atof(optarg)); break; case 'S': video_ad=rint(atof(optarg)); break; case 'f': video_hzn=rint(atof(optarg)); break; case 'F': video_hzd=rint(atof(optarg)); break; default: usage(); } } while(optind<argc){ /* assume that anything following the options must be a filename */ id_file(argv[optind]); optind++; } #ifdef THEORA_PERF_DATA # ifdef WIN32 QueryPerformanceCounter(&start_time); # endif #endif /* yayness. Set up Ogg output stream */ srand(time(NULL)); { /* need two inequal serial numbers */ int serial1, serial2; serial1 = rand(); serial2 = rand(); if (serial1 == serial2) serial2++; ogg_stream_init(&to,serial1); ogg_stream_init(&vo,serial2); } /* Set up Theora encoder */ if(!video){ fprintf(stderr,"No video files submitted for compression?\n"); exit(1); } /* Theora has a divisible-by-sixteen restriction for the encoded video size */ /* scale the frame size up to the nearest /16 and calculate offsets */ video_x=((frame_x + 15) >>4)<<4; video_y=((frame_y + 15) >>4)<<4; /* We force the offset to be even. This ensures that the chroma samples align properly with the luma samples. */ frame_x_offset=((video_x-frame_x)/2)&~1; frame_y_offset=((video_y-frame_y)/2)&~1; theora_info_init(&ti); ti.width=video_x; ti.height=video_y; ti.frame_width=frame_x; ti.frame_height=frame_y; ti.offset_x=frame_x_offset; ti.offset_y=frame_y_offset; ti.fps_numerator=video_hzn; ti.fps_denominator=video_hzd; ti.aspect_numerator=video_an; ti.aspect_denominator=video_ad; ti.colorspace=OC_CS_UNSPECIFIED; ti.pixelformat=OC_PF_420; ti.target_bitrate=video_r; ti.quality=video_q; ti.dropframes_p=0; ti.quick_p=1; ti.keyframe_auto_p=1; ti.keyframe_frequency=64; ti.keyframe_frequency_force=64; ti.keyframe_data_target_bitrate=video_r*1.5; ti.keyframe_auto_threshold=80; ti.keyframe_mindistance=8; ti.noise_sensitivity=1; theora_encode_init(&td,&ti); theora_info_clear(&ti); /* initialize Vorbis too, assuming we have audio to compress. */ if(audio){ vorbis_info_init(&vi); if(audio_q>-99) ret = vorbis_encode_init_vbr(&vi,audio_ch,audio_hz,audio_q); else ret = vorbis_encode_init(&vi,audio_ch,audio_hz,-1,audio_r,-1); if(ret){ fprintf(stderr,"The Vorbis encoder could not set up a mode according to\n" "the requested quality or bitrate.\n\n"); exit(1); } vorbis_comment_init(&vc); vorbis_analysis_init(&vd,&vi); vorbis_block_init(&vd,&vb); } /* write the bitstream header packets with proper page interleave */ /* first packet will get its own page automatically */ theora_encode_header(&td,&op); ogg_stream_packetin(&to,&op); if(ogg_stream_pageout(&to,&og)!=1){ fprintf(stderr,"Internal Ogg library error.\n"); exit(1); } fwrite(og.header,1,og.header_len,outfile); fwrite(og.body,1,og.body_len,outfile); /* create the remaining theora headers */ theora_comment_init(&tc); theora_encode_comment(&tc,&op); ogg_stream_packetin(&to,&op); /*theora_encode_comment() doesn't take a theora_state parameter, so it has to allocate its own buffer to pass back the packet data. If we don't free it here, we'll leak. libogg2 makes this much cleaner: the stream owns the buffer after you call packetin in libogg2, but this is not true in libogg1.*/ free(op.packet); theora_encode_tables(&td,&op); ogg_stream_packetin(&to,&op); if(audio){ ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); ogg_stream_packetin(&vo,&header); /* automatically placed in its own page */ if(ogg_stream_pageout(&vo,&og)!=1){ fprintf(stderr,"Internal Ogg library error.\n"); exit(1); } fwrite(og.header,1,og.header_len,outfile); fwrite(og.body,1,og.body_len,outfile); /* remaining vorbis header packets */ ogg_stream_packetin(&vo,&header_comm); ogg_stream_packetin(&vo,&header_code); } /* Flush the rest of our headers. This ensures the actual data in each stream will start on a new page, as per spec. */ while(1){ int result = ogg_stream_flush(&to,&og); if(result<0){ /* can't get here */ fprintf(stderr,"Internal Ogg library error.\n"); exit(1); } if(result==0)break; fwrite(og.header,1,og.header_len,outfile); fwrite(og.body,1,og.body_len,outfile); } if(audio){ while(1){ int result=ogg_stream_flush(&vo,&og); if(result<0){ /* can't get here */ fprintf(stderr,"Internal Ogg library error.\n"); exit(1); } if(result==0)break; fwrite(og.header,1,og.header_len,outfile); fwrite(og.body,1,og.body_len,outfile); } } /* setup complete. Raw processing loop */ fprintf(stderr,"Compressing....\n"); while(1){ ogg_page audiopage; ogg_page videopage; /* is there an audio page flushed? If not, fetch one if possible */ audioflag=fetch_and_process_audio(audio,&audiopage,&vo,&vd,&vb,audioflag); /* is there a video page flushed? If not, fetch one if possible */ videoflag=fetch_and_process_video(video,&videopage,&to,&td,videoflag); /* no pages of either? Must be end of stream. */ if(!audioflag && !videoflag)break; /* which is earlier; the end of the audio page or the end of the video page? Flush the earlier to stream */ { int audio_or_video=-1; double audiotime= audioflag?vorbis_granule_time(&vd,ogg_page_granulepos(&audiopage)):-1; double videotime= videoflag?theora_granule_time(&td,ogg_page_granulepos(&videopage)):-1; if(!audioflag){ audio_or_video=1; } else if(!videoflag) { audio_or_video=0; } else { if(audiotime<videotime) audio_or_video=0; else audio_or_video=1; } if(audio_or_video==1){ /* flush a video page */ video_bytesout+=fwrite(videopage.header,1,videopage.header_len,outfile); video_bytesout+=fwrite(videopage.body,1,videopage.body_len,outfile); videoflag=0; timebase=videotime; }else{ /* flush an audio page */ audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,outfile); audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,outfile); audioflag=0; timebase=audiotime; } { int hundredths=timebase*100-(long)timebase*100; int seconds=(long)timebase%60; int minutes=((long)timebase/60)%60; int hours=(long)timebase/3600; if(audio_or_video) vkbps=rint(video_bytesout*8./timebase*.001); else akbps=rint(audio_bytesout*8./timebase*.001); fprintf(stderr, "\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps ", hours,minutes,seconds,hundredths,akbps,vkbps); } } } /* clear out state */ if(audio){ ogg_stream_clear(&vo); vorbis_block_clear(&vb); vorbis_dsp_clear(&vd); vorbis_comment_clear(&vc); vorbis_info_clear(&vi); } if(video){ ogg_stream_clear(&to); theora_clear(&td); } if(outfile && outfile!=stdout)fclose(outfile); fprintf(stderr,"\r \ndone.\n\n"); #ifdef THEORA_PERF_DATA # ifdef WIN32 QueryPerformanceCounter(&final_time); elapsed_ticks = final_time.QuadPart - start_time.QuadPart; ticks_per_second; QueryPerformanceFrequency(&ticks_per_second); elapsed_secs = elapsed_ticks / ticks_per_second.QuadPart; elapsed_sec_mod = elapsed_ticks % ticks_per_second.QuadPart; elapsed_secs_dbl = elapsed_secs; elapsed_secs_dbl += ((double)elapsed_sec_mod / (double)ticks_per_second.QuadPart); printf("Encode time = %lld ticks\n", elapsed_ticks); printf("~%lld and %lld / %lld seconds\n", elapsed_secs, elapsed_sec_mod, ticks_per_second.QuadPart); printf("~%Lf seconds\n", elapsed_secs_dbl); # endif #endif return(0); }