bool FVoiceDecoderOpus::Init(int32 InSampleRate, int32 InNumChannels) { UE_LOG(LogVoiceDecode, Display, TEXT("DecoderVersion: %s"), ANSI_TO_TCHAR(opus_get_version_string())); SampleRate = InSampleRate; NumChannels = InNumChannels; FrameSize = SampleRate / 50; int32 DecSize = 0; int32 DecError = 0; #if USE_UE4_MEM_ALLOC DecSize = opus_decoder_get_size(NumChannels); Decoder = (OpusDecoder*)FMemory::Malloc(DecSize); DecError = opus_decoder_init(Decoder, SampleRate, NumChannels); #else Decoder = opus_decoder_create(SampleRate, NumChannels, &DecError); #endif if (DecError != OPUS_OK) { UE_LOG(LogVoiceDecode, Warning, TEXT("Failed to init Opus Decoder: %s"), ANSI_TO_TCHAR(opus_strerror(DecError))); Destroy(); } return DecError == OPUS_OK; }
int main(int _argc, char **_argv) { const char * oversion; const char * env_seed; int env_used; if(_argc>2) { fprintf(stderr,"Usage: %s [<seed>]\n",_argv[0]); return 1; } env_used=0; env_seed=getenv("SEED"); if(_argc>1)iseed=atoi(_argv[1]); else if(env_seed) { iseed=atoi(env_seed); env_used=1; } else iseed=(opus_uint32)time(NULL)^((getpid()&65535)<<16); Rw=Rz=iseed; oversion=opus_get_version_string(); if(!oversion)test_failed(); fprintf(stderr,"Testing %s decoder. Random seed: %u (%.4X)\n", oversion, iseed, fast_rand() % 65535); if(env_used)fprintf(stderr," Random seed set from the environment (SEED=%s).\n", env_seed); /*Setting TEST_OPUS_NOFUZZ tells the tool not to send garbage data into the decoders. This is helpful because garbage data may cause the decoders to clip, which angers CLANG IOC.*/ test_decoder_code0(getenv("TEST_OPUS_NOFUZZ")!=NULL); return 0; }
void OggOpusFile::WriteHeader() { /*The Identification Header is 19 bytes, plus a Channel Mapping Table for mapping families other than 0. The Channel Mapping Table is 2 bytes + 1 byte per channel. Because the maximum number of channels is 255, the maximum size of this header is 19 + 2 + 255 = 276 bytes.*/ unsigned char header_data[276]; const char *opus_version; opus_version=opus_get_version_string(); comment_init(&inopt.comments, &inopt.comments_length, opus_version); // snprintf(ENCODER_string, sizeof(ENCODER_string), "opusenc from %s %s",PACKAGE_NAME,"1.5"); CStdString encode_string; encode_string.Format("opusenc from %s 1.5", PACKAGE_NAME); strcpy(ENCODER_string, encode_string.c_str()); comment_add(&inopt.comments, &inopt.comments_length, "ENCODER", ENCODER_string); int packet_size=opus_header_to_packet(&header, header_data, sizeof(header_data)); op.packet=header_data; op.bytes=packet_size; op.b_o_s=1; op.e_o_s=0; op.granulepos=0; op.packetno=0; ogg_stream_packetin(&os, &op); while((ret=ogg_stream_flush(&os, &og))){ if(!ret)break; ret=oe_write_page(&og); if(ret!=og.header_len+og.body_len){ fprintf(stderr,"Error: failed writing header to output stream\n"); exit(1); } bytes_written+=ret; pages_out++; } comment_pad(&inopt.comments, &inopt.comments_length, comment_padding); op.packet=(unsigned char *)inopt.comments; op.bytes=inopt.comments_length; op.b_o_s=0; op.e_o_s=0; op.granulepos=0; op.packetno=1; ogg_stream_packetin(&os, &op); /* writing the rest of the Opus header packets */ while((ret=ogg_stream_flush(&os, &og))){ if(!ret)break; ret=oe_write_page(&og); if(ret!=og.header_len + og.body_len){ fprintf(stderr,"Error: failed writing header to output stream\n"); exit(1); } bytes_written+=ret; pages_out++; } }
/***************************************************************************** * ProcessHeaders: process Opus headers. *****************************************************************************/ static int ProcessHeaders( decoder_t *p_dec ) { ogg_packet oggpacket; unsigned pi_size[XIPH_MAX_HEADER_COUNT]; void *pp_data[XIPH_MAX_HEADER_COUNT]; unsigned i_count; int i_extra = p_dec->fmt_in.i_extra; uint8_t *p_extra = p_dec->fmt_in.p_extra; /* If we have no header (e.g. from RTP), make one. */ bool b_dummy_header = false; if( !i_extra ) { OpusHeader header; opus_prepare_header( p_dec->fmt_in.audio.i_channels, p_dec->fmt_in.audio.i_rate, &header ); if( opus_write_header( &p_extra, &i_extra, &header, opus_get_version_string() ) ) return VLC_ENOMEM; b_dummy_header = true; } if( xiph_SplitHeaders( pi_size, pp_data, &i_count, i_extra, p_extra ) ) { if( b_dummy_header ) free( p_extra ); return VLC_EGENERIC; } if( i_count < 2 ) { if( b_dummy_header ) free( p_extra ); return VLC_EGENERIC; } oggpacket.granulepos = -1; oggpacket.e_o_s = 0; oggpacket.packetno = 0; /* Take care of the initial Opus header */ oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */ oggpacket.bytes = pi_size[0]; oggpacket.packet = pp_data[0]; int ret = ProcessInitialHeader( p_dec, &oggpacket ); if (ret != VLC_SUCCESS) msg_Err( p_dec, "initial Opus header is corrupted" ); if( b_dummy_header ) free( p_extra ); return ret; }
OpusPluginEncoder(const PluginCodec_Definition * defn) : OpusPluginCodec(defn) , m_encoder(NULL) , m_dynamicPacketLoss(0) , m_useDTX(false) , m_bitRate(12000) { PTRACE(4, MY_CODEC_LOG, "Encoder created: $Revision$, version \"" << opus_get_version_string() << '"'); }
int opus_enc_init(opus_enc *opus) { int err; err = 0; opus->header = (OpusHeader *)calloc(1, sizeof(OpusHeader)); opus->header_data = (unsigned char *)calloc (1, 1024); opus->tags = (unsigned char *)calloc (1, 1024); opus->buffer = (unsigned char *)calloc (1, 4 * 4096); srand(time(NULL)); ogg_stream_init(&opus->os, rand()); opus->header->gain = 0; opus->header->channels = opus->channel; if ((opus->bitrate < 8000) || (opus->bitrate > 320000)) { opus->bitrate = DEFAULT_OPUS_BITRATE; } opus->header->input_sample_rate = 48000; opus->encoder = opus_encoder_create (opus->header->input_sample_rate, opus->channel, OPUS_APPLICATION_AUDIO, &err); opus_encoder_ctl (opus->encoder, OPUS_SET_BITRATE(opus->bitrate)); if (opus->encoder == NULL) { printf("Opus Encoder creation error: %s\n", opus_strerror (err)); return 1; } opus->last_bitrate = opus->bitrate; opus_encoder_ctl (opus->encoder, OPUS_GET_LOOKAHEAD (&opus->header->preskip)); opus->header_size = opus_header_to_packet (opus->header, opus->header_data, 100); opus->tags_size = 8 + 4 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER=") + strlen (VERSION); memcpy (opus->tags, "OpusTags", 8); opus->tags[8] = strlen (opus_get_version_string ()); memcpy (opus->tags + 12, opus_get_version_string (), strlen (opus_get_version_string ())); opus->tags[12 + strlen (opus_get_version_string ())] = 1; opus->tags[12 + strlen (opus_get_version_string ()) + 4] = strlen ("ENCODER=") + strlen (VERSION); memcpy (opus->tags + 12 + strlen (opus_get_version_string ()) + 4 + 4, "ENCODER=", strlen ("ENCODER=")); memcpy (opus->tags + 12 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER="), VERSION, strlen (VERSION)); //printf("Opus Encoder Created\n"); return 0; }
int16_t WebRtcOpus_Version(char *version, int16_t lenBytes) { const char *opus = opus_get_version_string(); if (opus == NULL || version == NULL || lenBytes < 0) { return -1; } strncpy(version, opus, lenBytes); version[lenBytes-1] = '\0'; return 0; }
void cmdAbout(const std::string& args) { // TODO: replace this with a GUI window narf::console->println(""); narf::console->println("About NarfBlock"); narf::console->println("Version: " VERSION_STR); narf::console->println(""); narf::console->println("Authors:"); auto authors = narf::util::tokenize(VERSION_AUTHORS, '\n'); for (auto& a : authors) { narf::console->println(a); } narf::console->println(""); auto credits = narf::util::tokenize(EMBED_STRING(extra_credits_txt), '\n'); for (auto& c : credits) { narf::console->println(c); } narf::console->println(""); narf::console->println("Library versions:"); narf::console->println("ENet " + std::to_string(ENET_VERSION_MAJOR) + "." + std::to_string(ENET_VERSION_MINOR) + "." + std::to_string(ENET_VERSION_PATCH)); SDL_version sdl; SDL_GetVersion(&sdl); narf::console->println("SDL " + std::to_string(sdl.major) + "." + std::to_string(sdl.minor) + "." + std::to_string(sdl.patch)); narf::console->println("zlib " + std::string(zlibVersion())); auto png = png_access_version_number(); auto pngMajor = png / 10000; auto pngMinor = (png / 100) % 100; auto pngRelease = png % 100; narf::console->println("libpng " + std::to_string(pngMajor) + "." + std::to_string(pngMinor) + "." + std::to_string(pngRelease)); FT_Library ftlib; FT_Init_FreeType(&ftlib); FT_Int ftMajor, ftMinor, ftPatch; FT_Library_Version(ftlib, &ftMajor, &ftMinor, &ftPatch); FT_Done_FreeType(ftlib); narf::console->println("FreeType " + std::to_string(ftMajor) + "." + std::to_string(ftMinor) + "." + std::to_string(ftPatch)); narf::console->println(opus_get_version_string()); narf::console->println(""); narf::console->println("OpenGL information:"); narf::console->println("OpenGL version " + std::string(display->glVersion)); narf::console->println("GLSL version " + std::string(display->glslVersion)); narf::console->println("GL context version " + std::to_string(display->glContextVersionMajor) + "." + std::to_string(display->glContextVersionMinor)); }
bool FVoiceEncoderOpus::Init(int32 InSampleRate, int32 InNumChannels) { UE_LOG(LogVoiceEncode, Display, TEXT("EncoderVersion: %s"), ANSI_TO_TCHAR(opus_get_version_string())); SampleRate = InSampleRate; NumChannels = InNumChannels; // 20ms frame sizes are a good choice for most applications (1000ms / 20ms = 50) FrameSize = SampleRate / NUM_OPUS_FRAMES_PER_SEC; //MaxFrameSize = FrameSize * MAX_OPUS_FRAMES; int32 EncError = 0; #if USE_UE4_MEM_ALLOC int32 EncSize = opus_encoder_get_size(NumChannels); Encoder = (OpusEncoder*)FMemory::Malloc(EncSize); EncError = opus_encoder_init(Encoder, SampleRate, NumChannels, OPUS_APPLICATION_VOIP); #else Encoder = opus_encoder_create(SampleRate, NumChannels, OPUS_APPLICATION_VOIP, &EncError); #endif if (EncError != OPUS_OK) { UE_LOG(LogVoiceEncode, Warning, TEXT("Failed to init Opus Encoder: %s"), ANSI_TO_TCHAR(opus_strerror(EncError))); Destroy(); } // Turn on variable bit rate encoding int32 UseVbr = 1; opus_encoder_ctl(Encoder, OPUS_SET_VBR(UseVbr)); // Turn off constrained VBR int32 UseCVbr = 0; opus_encoder_ctl(Encoder, OPUS_SET_VBR_CONSTRAINT(UseCVbr)); // Complexity (1-10) int32 Complexity = 1; opus_encoder_ctl(Encoder, OPUS_SET_COMPLEXITY(Complexity)); // Forward error correction int32 InbandFEC = 0; opus_encoder_ctl(Encoder, OPUS_SET_INBAND_FEC(InbandFEC)); #if DEBUG_OPUS DebugEncoderInfo(Encoder); #endif // DEBUG_OPUS return EncError == OPUS_OK; }
static char *comment_init(size_t *length) { /*The 'vendor' field should be the actual encoding library used.*/ const char *vendor_string = opus_get_version_string(); int vendor_length = strlen(vendor_string); int user_comment_list_length = 0; int len = 8 + 4 + vendor_length + 4; char *p = malloc(len); if (p == NULL) return NULL; memcpy(p, "OpusTags", 8); SetDWLE(p + 8, vendor_length); memcpy(p + 12, vendor_string, vendor_length); SetDWLE(p + 12 + vendor_length, user_comment_list_length); *length = len; return p; }
already_AddRefed<TrackMetadataBase> OpusTrackEncoder::GetMetadata() { PROFILER_LABEL("OpusTrackEncoder", "GetMetadata", js::ProfileEntry::Category::OTHER); { // Wait if mEncoder is not initialized. ReentrantMonitorAutoEnter mon(mReentrantMonitor); while (!mCanceled && !mInitialized) { mReentrantMonitor.Wait(); } } if (mCanceled || mEncodingComplete) { return nullptr; } RefPtr<OpusMetadata> meta = new OpusMetadata(); mLookahead = 0; int error = opus_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&mLookahead)); if (error != OPUS_OK) { mLookahead = 0; } // The ogg time stamping and pre-skip is always timed at 48000. SerializeOpusIdHeader(mChannels, mLookahead * (kOpusSamplingRate / GetOutputSampleRate()), mSamplingRate, &meta->mIdHeader); nsCString vendor; vendor.AppendASCII(opus_get_version_string()); nsTArray<nsCString> comments; comments.AppendElement(NS_LITERAL_CSTRING("ENCODER=Mozilla" MOZ_APP_UA_VERSION)); SerializeOpusCommentHeader(vendor, comments, &meta->mCommentHeader); return meta.forget(); }
void version_short(void) { printf("opusdec %s %s (using %s)\n",PACKAGE,VERSION,opus_get_version_string()); printf("Copyright (C) 2008-2012 Xiph.Org Foundation\n"); }
krad_opus_t *krad_opus_encoder_create (int channels, int input_sample_rate, int bitrate, int application) { int c; krad_opus_t *krad_opus = calloc(1, sizeof(krad_opus_t)); krad_opus->opus_header = calloc(1, sizeof(OpusHeader)); krad_opus->input_sample_rate = input_sample_rate; krad_opus->channels = channels; krad_opus->bitrate = bitrate; krad_opus->application = application; krad_opus->complexity = DEFAULT_OPUS_COMPLEXITY; krad_opus->signal = OPUS_AUTO; krad_opus->frame_size = DEFAULT_OPUS_FRAME_SIZE; krad_opus->bandwidth = OPUS_BANDWIDTH_FULLBAND; krad_opus->new_frame_size = krad_opus->frame_size; krad_opus->new_complexity = krad_opus->complexity; krad_opus->new_bitrate = krad_opus->bitrate; krad_opus->new_signal = krad_opus->signal; krad_opus->new_bandwidth = krad_opus->bandwidth; for (c = 0; c < krad_opus->channels; c++) { krad_opus->ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE); krad_opus->resampled_ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE); krad_opus->samples[c] = malloc(16 * 8192); krad_opus->resampled_samples[c] = malloc(16 * 8192); krad_opus->src_resampler[c] = src_new (KRAD_OPUS_SRC_QUALITY, 1, &krad_opus->src_error[c]); if (krad_opus->src_resampler[c] == NULL) { failfast ("Krad Opus Encoder: src resampler error: %s", src_strerror (krad_opus->src_error[c])); } krad_opus->src_data[c].src_ratio = 48000.0 / krad_opus->input_sample_rate; } if (krad_opus->channels < 3) { krad_opus->streams = 1; if (krad_opus->channels == 2) { krad_opus->coupled_streams = 1; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 1; } else { krad_opus->coupled_streams = 0; krad_opus->mapping[0] = 0; } krad_opus->opus_header->channel_mapping = 0; } else { krad_opus->opus_header->channel_mapping = 1; switch (krad_opus->channels) { case 3: krad_opus->streams = 2; krad_opus->coupled_streams = 1; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 1; krad_opus->mapping[2] = 2; case 4: krad_opus->streams = 2; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 1; krad_opus->mapping[2] = 2; krad_opus->mapping[3] = 3; case 5: krad_opus->streams = 3; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 4; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; case 6: krad_opus->streams = 4; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 4; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; krad_opus->mapping[5] = 5; case 7: krad_opus->streams = 5; krad_opus->coupled_streams = 2; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 4; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; krad_opus->mapping[5] = 5; krad_opus->mapping[6] = 6; case 8: krad_opus->streams = 5; krad_opus->coupled_streams = 3; krad_opus->mapping[0] = 0; krad_opus->mapping[1] = 6; krad_opus->mapping[2] = 1; krad_opus->mapping[3] = 2; krad_opus->mapping[4] = 3; krad_opus->mapping[5] = 4; krad_opus->mapping[6] = 5; krad_opus->mapping[7] = 7; } } krad_opus->opus_header->channels = krad_opus->channels; krad_opus->opus_header->nb_streams = krad_opus->streams; krad_opus->opus_header->nb_coupled = krad_opus->coupled_streams; memcpy (krad_opus->opus_header->stream_map, krad_opus->mapping, 256); krad_opus->encoder = opus_multistream_encoder_create (48000, krad_opus->channels, krad_opus->streams, krad_opus->coupled_streams, krad_opus->mapping, krad_opus->application, &krad_opus->err); if (krad_opus->err != OPUS_OK) { failfast ("Krad Opus Encoder: Cannot create encoder: %s", opus_strerror (krad_opus->err)); } opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_GET_LOOKAHEAD (&krad_opus->lookahead)); krad_opus->opus_header->preskip = krad_opus->lookahead; krad_opus->opus_header->gain = 0; krad_opus->opus_header->input_sample_rate = 48000; if (opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_BITRATE (krad_opus->bitrate)) != OPUS_OK) { failfast ("Krad Opus Encoder: bitrate request failed"); } krad_opus->header_data_size = opus_header_to_packet (krad_opus->opus_header, krad_opus->header_data, 100); krad_opus->krad_codec_header.codec = OPUS; krad_opus->krad_codec_header.header[0] = krad_opus->header_data; krad_opus->krad_codec_header.header_size[0] = krad_opus->header_data_size; krad_opus->krad_codec_header.header_combined = krad_opus->header_data; krad_opus->krad_codec_header.header_combined_size = krad_opus->header_data_size; krad_opus->krad_codec_header.header_count = 2; krad_opus->krad_codec_header.header_size[1] = 8 + 4 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER=") + strlen (APPVERSION); krad_opus->opustags_header = calloc (1, krad_opus->krad_codec_header.header_size[1]); memcpy (krad_opus->opustags_header, "OpusTags", 8); krad_opus->opustags_header[8] = strlen (opus_get_version_string ()); memcpy (krad_opus->opustags_header + 12, opus_get_version_string (), strlen (opus_get_version_string ())); krad_opus->opustags_header[12 + strlen (opus_get_version_string ())] = 1; krad_opus->opustags_header[12 + strlen (opus_get_version_string ()) + 4] = strlen ("ENCODER=") + strlen (APPVERSION); memcpy (krad_opus->opustags_header + 12 + strlen (opus_get_version_string ()) + 4 + 4, "ENCODER=", strlen ("ENCODER=")); memcpy (krad_opus->opustags_header + 12 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER="), APPVERSION, strlen (APPVERSION)); krad_opus->krad_codec_header.header[1] = krad_opus->opustags_header; return krad_opus; }
OpusPluginDecoder(const PluginCodec_Definition * defn) : OpusPluginCodec(defn) , m_decoder(NULL) { PTRACE(4, MY_CODEC_LOG, "Decoder created: $Revision$, version \"" << opus_get_version_string() << '"'); }
JNIEXPORT jstring JNICALL Java_org_echocat_jopus_OpusJNI_getVersionString (JNIEnv *env, jclass thisClass) { const char* versionString = opus_get_version_string(); return (*env)->NewStringUTF(env, versionString); }
static int OpenEncoder(vlc_object_t *p_this) { encoder_t *enc = (encoder_t *)p_this; if (enc->fmt_out.i_codec != VLC_CODEC_OPUS) return VLC_EGENERIC; encoder_sys_t *sys = malloc(sizeof(*sys)); if (!sys) return VLC_ENOMEM; int status = VLC_SUCCESS; sys->buffer = NULL; sys->enc = NULL; enc->pf_encode_audio = Encode; enc->fmt_in.i_codec = VLC_CODEC_FL32; enc->fmt_in.audio.i_rate = /* Only 48kHz */ enc->fmt_out.audio.i_rate = 48000; enc->fmt_out.audio.i_channels = enc->fmt_in.audio.i_channels; OpusHeader header; opus_prepare_header(enc->fmt_out.audio.i_channels, enc->fmt_out.audio.i_rate, &header); /* needed for max encoded size calculation */ sys->nb_streams = header.nb_streams; int err; sys->enc = opus_multistream_surround_encoder_create(enc->fmt_in.audio.i_rate, enc->fmt_in.audio.i_channels, header.channel_mapping, &header.nb_streams, &header.nb_coupled, header.stream_map, OPUS_APPLICATION_AUDIO, &err); if (err != OPUS_OK) { msg_Err(enc, "Could not create encoder: error %d", err); sys->enc = NULL; status = VLC_EGENERIC; goto error; } /* TODO: vbr, fec */ if( enc->fmt_out.i_bitrate ) opus_multistream_encoder_ctl(sys->enc, OPUS_SET_BITRATE( enc->fmt_out.i_bitrate )); /* Buffer for incoming audio, since opus only accepts frame sizes that are multiples of 2.5ms */ enc->p_sys = sys; sys->buffer = malloc(OPUS_FRAME_SIZE * header.channels * sizeof(float)); if (!sys->buffer) { status = VLC_ENOMEM; goto error; } sys->i_nb_samples = 0; sys->i_samples_delay = 0; int ret = opus_multistream_encoder_ctl(enc->p_sys->enc, OPUS_GET_LOOKAHEAD(&sys->i_samples_delay)); if (ret != OPUS_OK) msg_Err(enc, "Unable to get number of lookahead samples: %s\n", opus_strerror(ret)); header.preskip = sys->i_samples_delay; /* Now that we have preskip, we can write the header to extradata */ if (opus_write_header((uint8_t **) &enc->fmt_out.p_extra, &enc->fmt_out.i_extra, &header, opus_get_version_string())) { msg_Err(enc, "Failed to write header."); status = VLC_ENOMEM; goto error; } if (sys->i_samples_delay > 0) { const unsigned padding_samples = sys->i_samples_delay * enc->fmt_out.audio.i_channels; sys->padding = block_Alloc(padding_samples * sizeof(float)); if (!sys->padding) { status = VLC_ENOMEM; goto error; } sys->padding->i_nb_samples = sys->i_samples_delay; float *pad_ptr = (float *) sys->padding->p_buffer; memset(pad_ptr, 0, padding_samples * sizeof(float)); } else { sys->padding = NULL; } return status; error: if (sys->enc) opus_multistream_encoder_destroy(sys->enc); free(sys->buffer); free(sys); return status; }
static result_t encode_opus_file(char *filename, struct PCMReader *pcmreader, int quality, unsigned original_sample_rate) { const int multichannel = (pcmreader->channels > 2); const unsigned channel_mapping = (pcmreader->channels > 8 ? 255 : pcmreader->channels > 2); int stream_count; int coupled_stream_count; unsigned char stream_map[255]; int samples[BLOCK_SIZE * pcmreader->channels]; unsigned pcm_frames; result_t result = ENCODE_OK; FILE *output_file = NULL; ogg_stream_state ogg_stream; ogg_page ogg_page; OpusEncoder *opus_encoder = NULL; OpusMSEncoder *opus_ms_encoder = NULL; int error; opus_int16 *opus_samples = NULL; unsigned char opus_frame[OPUS_FRAME_LEN]; ogg_int64_t granulepos = 0; ogg_int64_t packetno = 0; opus_int32 preskip; /*open output file for writing*/ if ((output_file = fopen(filename, "w+b")) == NULL) { return ERR_IOERROR; } if (!multichannel) { if ((opus_encoder = opus_encoder_create(48000, pcmreader->channels, OPUS_APPLICATION_AUDIO, &error)) == NULL) { fclose(output_file); return ERR_ENCODER_INIT; } opus_encoder_ctl(opus_encoder, OPUS_SET_COMPLEXITY(quality)); opus_encoder_ctl(opus_encoder, OPUS_GET_LOOKAHEAD(&preskip)); } else { if ((opus_ms_encoder = opus_multistream_surround_encoder_create( 48000, pcmreader->channels, channel_mapping, &stream_count, &coupled_stream_count, stream_map, OPUS_APPLICATION_AUDIO, &error)) == NULL) { fclose(output_file); return ERR_ENCODER_INIT; } opus_multistream_encoder_ctl(opus_ms_encoder, OPUS_SET_COMPLEXITY(quality)); opus_multistream_encoder_ctl(opus_ms_encoder, OPUS_GET_LOOKAHEAD(&preskip)); } srand((unsigned)time(NULL)); ogg_stream_init(&ogg_stream, rand()); /*write header and comment packets to Ogg stream*/ { BitstreamRecorder *header = bw_open_bytes_recorder(BS_LITTLE_ENDIAN); BitstreamWriter *header_w =(BitstreamWriter*)header; BitstreamRecorder *comment = bw_open_bytes_recorder(BS_LITTLE_ENDIAN); BitstreamWriter *comment_w = (BitstreamWriter*)comment; int i; /*write header packet to Ogg stream*/ const char opushead[] = "OpusHead"; const char opuscomment[] = "OpusTags"; const char *vendor_string = opus_get_version_string(); const size_t vendor_string_len = strlen(vendor_string); ogg_packet packet_head; ogg_packet packet_tags; header_w->write_bytes(header_w, (uint8_t*)opushead, (unsigned)strlen(opushead)); header_w->write(header_w, 8, 1); /*version*/ header_w->write(header_w, 8, pcmreader->channels); header_w->write(header_w, 16, preskip); header_w->write(header_w, 32, original_sample_rate); header_w->write(header_w, 16, 0); /*output gain*/ header_w->write(header_w, 8, channel_mapping); if (channel_mapping != 0) { header_w->write(header_w, 8, stream_count); header_w->write(header_w, 8, coupled_stream_count); for (i = 0; i < pcmreader->channels; i++) { header_w->write(header_w, 8, stream_map[i]); } } packet_head.packet = malloc(header->bytes_written(header)); header->data(header, (uint8_t*)packet_head.packet); packet_head.bytes = header->bytes_written(header); packet_head.b_o_s = 1; packet_head.e_o_s = 0; packet_head.granulepos = 0; packet_head.packetno = packetno++; header->close(header); ogg_stream_packetin(&ogg_stream, &packet_head); for (i = ogg_stream_flush(&ogg_stream, &ogg_page); i != 0; i = ogg_stream_flush(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } free(packet_head.packet); /*write comment packet to Ogg stream*/ comment_w->write_bytes(comment_w, (uint8_t*)opuscomment, (unsigned)strlen(opuscomment)); comment_w->write(comment_w, 32, (unsigned)vendor_string_len); comment_w->write_bytes(comment_w, (uint8_t*)vendor_string, (unsigned)vendor_string_len); comment_w->write(comment_w, 32, 0); packet_tags.packet = malloc(comment->bytes_written(comment)); comment->data(comment, (uint8_t*)packet_tags.packet); packet_tags.bytes = comment->bytes_written(comment); packet_tags.b_o_s = 0; packet_tags.e_o_s = 0; packet_tags.granulepos = 0; packet_tags.packetno = packetno++; comment->close(comment); ogg_stream_packetin(&ogg_stream, &packet_tags); for (i = ogg_stream_flush(&ogg_stream, &ogg_page); i != 0; i = ogg_stream_flush(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } free(packet_tags.packet); } opus_samples = malloc(sizeof(opus_int16) * pcmreader->channels * BLOCK_SIZE); pcm_frames = pcmreader->read(pcmreader, BLOCK_SIZE, samples); if (!pcm_frames && (pcmreader->status != PCM_OK)) { result = ERR_PCMREADER; goto cleanup; } /*for each non-empty FrameList from PCMReader, encode Opus frame*/ while (pcm_frames) { const int short_framelist = (pcm_frames < BLOCK_SIZE); unsigned i; opus_int32 encoded_size; ogg_packet packet; granulepos += pcm_frames; /*pad FrameList with additional null samples if necessary*/ memset(samples + pcm_frames * pcmreader->channels, 0, sizeof(int) * (BLOCK_SIZE - pcm_frames) * pcmreader->channels); /*rearrange channels to Vorbis order if necessary*/ reorder_channels(pcmreader->channel_mask, BLOCK_SIZE, samples); /*place samples in interleaved buffer*/ for (i = 0; i < (pcm_frames * pcmreader->channels); i++) { opus_samples[i] = (opus_int16)samples[i]; } /*call opus_encode on interleaved buffer to get next packet*/ if (!multichannel) { encoded_size = opus_encode(opus_encoder, opus_samples, BLOCK_SIZE, opus_frame, OPUS_FRAME_LEN); } else { encoded_size = opus_multistream_encode(opus_ms_encoder, opus_samples, BLOCK_SIZE, opus_frame, OPUS_FRAME_LEN); } /*get next FrameList to encode*/ pcm_frames = pcmreader->read(pcmreader, BLOCK_SIZE, samples); if (!pcm_frames && (pcmreader->status != PCM_OK)) { result = ERR_PCMREADER; goto cleanup; } /*dump Opus packet to Ogg stream*/ /*do this *after* reading the next FrameList in order to detect the end of stream properly based on whether the FrameList has no frames*/ packet.packet = (unsigned char *)opus_frame; packet.bytes = encoded_size; packet.b_o_s = 0; packet.e_o_s = (short_framelist || (pcm_frames == 0)); packet.granulepos = granulepos; packet.packetno = packetno; ogg_stream_packetin(&ogg_stream, &packet); while (ogg_stream_pageout(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } } /*flush any remaining Ogg pages to disk*/ while (ogg_stream_flush(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } cleanup: fclose(output_file); ogg_stream_clear(&ogg_stream); if (!multichannel) { opus_encoder_destroy(opus_encoder); } else { opus_multistream_encoder_destroy(opus_ms_encoder); } free(opus_samples); return result; }
int initRecorder(const char *path) { cleanupRecorder(); if (!path) { return 0; } _fileOs = fopen(path, "wb"); if (!_fileOs) { return 0; } inopt.rate = rate; inopt.gain = 0; inopt.endianness = 0; inopt.copy_comments = 0; inopt.rawmode = 1; inopt.ignorelength = 1; inopt.samplesize = 16; inopt.channels = 1; inopt.skip = 0; comment_init(&inopt.comments, &inopt.comments_length, opus_get_version_string()); if (rate > 24000) { coding_rate = 48000; } else if (rate > 16000) { coding_rate = 24000; } else if (rate > 12000) { coding_rate = 16000; } else if (rate > 8000) { coding_rate = 12000; } else { coding_rate = 8000; } if (rate != coding_rate) { LOGE("Invalid rate"); return 0; } header.channels = 1; header.channel_mapping = 0; header.input_sample_rate = rate; header.gain = inopt.gain; header.nb_streams = 1; int result = OPUS_OK; _encoder = opus_encoder_create(coding_rate, 1, OPUS_APPLICATION_AUDIO, &result); if (result != OPUS_OK) { LOGE("Error cannot create encoder: %s", opus_strerror(result)); return 0; } min_bytes = max_frame_bytes = (1275 * 3 + 7) * header.nb_streams; _packet = malloc(max_frame_bytes); result = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate)); if (result != OPUS_OK) { LOGE("Error OPUS_SET_BITRATE returned: %s", opus_strerror(result)); return 0; } #ifdef OPUS_SET_LSB_DEPTH result = opus_encoder_ctl(_encoder, OPUS_SET_LSB_DEPTH(max(8, min(24, inopt.samplesize)))); if (result != OPUS_OK) { LOGE("Warning OPUS_SET_LSB_DEPTH returned: %s", opus_strerror(result)); } #endif opus_int32 lookahead; result = opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&lookahead)); if (result != OPUS_OK) { LOGE("Error OPUS_GET_LOOKAHEAD returned: %s", opus_strerror(result)); return 0; } inopt.skip += lookahead; header.preskip = (int)(inopt.skip * (48000.0 / coding_rate)); inopt.extraout = (int)(header.preskip * (rate / 48000.0)); if (ogg_stream_init(&os, rand()) == -1) { LOGE("Error: stream init failed"); return 0; } unsigned char header_data[100]; int packet_size = opus_header_to_packet(&header, header_data, 100); op.packet = header_data; op.bytes = packet_size; op.b_o_s = 1; op.e_o_s = 0; op.granulepos = 0; op.packetno = 0; ogg_stream_packetin(&os, &op); while ((result = ogg_stream_flush(&os, &og))) { if (!result) { break; } int pageBytesWritten = writeOggPage(&og, _fileOs); if (pageBytesWritten != og.header_len + og.body_len) { LOGE("Error: failed writing header to output stream"); return 0; } bytes_written += pageBytesWritten; pages_out++; } comment_pad(&inopt.comments, &inopt.comments_length, comment_padding); op.packet = (unsigned char *)inopt.comments; op.bytes = inopt.comments_length; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = 1; ogg_stream_packetin(&os, &op); while ((result = ogg_stream_flush(&os, &og))) { if (result == 0) { break; } int writtenPageBytes = writeOggPage(&og, _fileOs); if (writtenPageBytes != og.header_len + og.body_len) { LOGE("Error: failed writing header to output stream"); return 0; } bytes_written += writtenPageBytes; pages_out++; } free(inopt.comments); return 1; }
int opusEncoder(int argc, char **argv) { static const input_format raw_format = {NULL, 0, raw_open, wav_close, "raw",N_("RAW file reader")}; int option_index=0; struct option long_options[] = { {"quiet", no_argument, NULL, 0}, {"bitrate", required_argument, NULL, 0}, {"hard-cbr",no_argument,NULL, 0}, {"vbr",no_argument,NULL, 0}, {"cvbr",no_argument,NULL, 0}, {"comp", required_argument, NULL, 0}, {"complexity", required_argument, NULL, 0}, {"framesize", required_argument, NULL, 0}, {"expect-loss", required_argument, NULL, 0}, {"downmix-mono",no_argument,NULL, 0}, {"downmix-stereo",no_argument,NULL, 0}, {"no-downmix",no_argument,NULL, 0}, {"max-delay", required_argument, NULL, 0}, {"serial", required_argument, NULL, 0}, {"save-range", required_argument, NULL, 0}, {"set-ctl-int", required_argument, NULL, 0}, {"help", no_argument, NULL, 0}, {"raw", no_argument, NULL, 0}, {"raw-bits", required_argument, NULL, 0}, {"raw-rate", required_argument, NULL, 0}, {"raw-chan", required_argument, NULL, 0}, {"raw-endianness", required_argument, NULL, 0}, {"ignorelength", no_argument, NULL, 0}, {"rate", required_argument, NULL, 0}, {"version", no_argument, NULL, 0}, {"version-short", no_argument, NULL, 0}, {"comment", required_argument, NULL, 0}, {"artist", required_argument, NULL, 0}, {"title", required_argument, NULL, 0}, {"album", required_argument, NULL, 0}, {"date", required_argument, NULL, 0}, {"genre", required_argument, NULL, 0}, {"picture", required_argument, NULL, 0}, {"padding", required_argument, NULL, 0}, {"discard-comments", no_argument, NULL, 0}, {"discard-pictures", no_argument, NULL, 0}, {0, 0, 0, 0} }; int i, ret; int cline_size; OpusMSEncoder *st; const char *opus_version; unsigned char *packet; float *input; /*I/O*/ oe_enc_opt inopt; const input_format *in_format; char *inFile; char *outFile; char *range_file; FILE *fin; FILE *fout; FILE *frange; ogg_stream_state os; ogg_page og; ogg_packet op; ogg_int64_t last_granulepos=0; ogg_int64_t enc_granulepos=0; ogg_int64_t original_samples=0; ogg_int32_t id=-1; int last_segments=0; int eos=0; OpusHeader header; char ENCODER_string[1024]; /*Counters*/ opus_int64 nb_encoded=0; opus_int64 bytes_written=0; opus_int64 pages_out=0; opus_int64 total_bytes=0; opus_int64 total_samples=0; opus_int32 nbBytes; opus_int32 nb_samples; opus_int32 peak_bytes=0; opus_int32 min_bytes; time_t start_time; time_t stop_time; time_t last_spin=0; int last_spin_len=0; /*Settings*/ int quiet=0; int max_frame_bytes; opus_int32 bitrate=-1; opus_int32 rate=48000; opus_int32 coding_rate=48000; opus_int32 frame_size=960; int chan=2; int with_hard_cbr=0; int with_cvbr=0; int expect_loss=0; int complexity=10; int downmix=0; int *opt_ctls_ctlval; int opt_ctls=0; int max_ogg_delay=48000; /*48kHz samples*/ int seen_file_icons=0; int comment_padding=512; int serialno; opus_int32 lookahead=0; #ifdef WIN_UNICODE int argc_utf8; char **argv_utf8; #endif if(query_cpu_support()){ fprintf(stderr,"\n\n** WARNING: This program was compiled with SSE%s\n",query_cpu_support()>1?"2":""); fprintf(stderr," but this CPU claims to lack these instructions. **\n\n"); } #ifdef WIN_UNICODE (void)argc; (void)argv; init_commandline_arguments_utf8(&argc_utf8, &argv_utf8); #endif opt_ctls_ctlval=NULL; frange=NULL; range_file=NULL; in_format=NULL; inopt.channels=chan; inopt.rate=coding_rate=rate; /* 0 dB gain is recommended unless you know what you're doing */ inopt.gain=0; inopt.samplesize=16; inopt.endianness=0; inopt.rawmode=0; inopt.ignorelength=0; inopt.copy_comments=1; inopt.copy_pictures=1; start_time = time(NULL); srand(((getpid()&65535)<<15)^start_time); serialno=rand(); opus_version=opus_get_version_string(); /*Vendor string should just be the encoder library, the ENCODER comment specifies the tool used.*/ comment_init(&inopt.comments, &inopt.comments_length, opus_version); // snprintf(ENCODER_string, sizeof(ENCODER_string), "opusenc from %s %s",PACKAGE_NAME,PACKAGE_VERSION); comment_add(&inopt.comments, &inopt.comments_length, "ENCODER", ENCODER_string); /*Process command-line options*/ cline_size=0; while(1){ int c; int save_cmd=1; c=getopt_long(argc_utf8, argv_utf8, "hV", long_options, &option_index); if(c==-1) break; switch(c){ case 0: if(strcmp(long_options[option_index].name,"quiet")==0){ quiet=1; }else if(strcmp(long_options[option_index].name,"bitrate")==0){ bitrate=atof(optarg)*1000.; }else if(strcmp(long_options[option_index].name,"hard-cbr")==0){ with_hard_cbr=1; with_cvbr=0; }else if(strcmp(long_options[option_index].name,"cvbr")==0){ with_cvbr=1; with_hard_cbr=0; }else if(strcmp(long_options[option_index].name,"vbr")==0){ with_cvbr=0; with_hard_cbr=0; }else if(strcmp(long_options[option_index].name,"help")==0){ usage(); return 0;//exit(0); }else if(strcmp(long_options[option_index].name,"version")==0){ opustoolsversion(opus_version); return 0;//exit(0); }else if(strcmp(long_options[option_index].name,"version-short")==0){ opustoolsversion_short(opus_version); return 0;//exit(0); }else if(strcmp(long_options[option_index].name,"ignorelength")==0){ inopt.ignorelength=1; }else if(strcmp(long_options[option_index].name,"raw")==0){ inopt.rawmode=1; save_cmd=0; }else if(strcmp(long_options[option_index].name,"raw-bits")==0){ inopt.rawmode=1; inopt.samplesize=atoi(optarg); save_cmd=0; if(inopt.samplesize!=8&&inopt.samplesize!=16&&inopt.samplesize!=24){ fprintf(stderr,"Invalid bit-depth: %s\n",optarg); fprintf(stderr,"--raw-bits must be one of 8,16, or 24\n"); return 0;//exit(1); } }else if(strcmp(long_options[option_index].name,"raw-rate")==0){ inopt.rawmode=1; inopt.rate=atoi(optarg); save_cmd=0; }else if(strcmp(long_options[option_index].name,"raw-chan")==0){ inopt.rawmode=1; inopt.channels=atoi(optarg); save_cmd=0; }else if(strcmp(long_options[option_index].name,"raw-endianness")==0){ inopt.rawmode=1; inopt.endianness=atoi(optarg); save_cmd=0; }else if(strcmp(long_options[option_index].name,"downmix-mono")==0){ downmix=1; }else if(strcmp(long_options[option_index].name,"downmix-stereo")==0){ downmix=2; }else if(strcmp(long_options[option_index].name,"no-downmix")==0){ downmix=-1; }else if(strcmp(long_options[option_index].name,"expect-loss")==0){ expect_loss=atoi(optarg); if(expect_loss>100||expect_loss<0){ fprintf(stderr,"Invalid expect-loss: %s\n",optarg); fprintf(stderr,"Expected loss is a percent and must be 0-100.\n"); return 0;//exit(1); } }else if(strcmp(long_options[option_index].name,"comp")==0 || strcmp(long_options[option_index].name,"complexity")==0){ complexity=atoi(optarg); if(complexity>10||complexity<0){ fprintf(stderr,"Invalid complexity: %s\n",optarg); fprintf(stderr,"Complexity must be 0-10.\n"); return 0;//exit(1); } }else if(strcmp(long_options[option_index].name,"framesize")==0){ if(strcmp(optarg,"2.5")==0)frame_size=120; else if(strcmp(optarg,"5")==0)frame_size=240; else if(strcmp(optarg,"10")==0)frame_size=480; else if(strcmp(optarg,"20")==0)frame_size=960; else if(strcmp(optarg,"40")==0)frame_size=1920; else if(strcmp(optarg,"60")==0)frame_size=2880; else{ fprintf(stderr,"Invalid framesize: %s\n",optarg); fprintf(stderr,"Framesize must be 2.5, 5, 10, 20, 40, or 60.\n"); return 0;//exit(1); } }else if(strcmp(long_options[option_index].name,"max-delay")==0){ max_ogg_delay=floor(atof(optarg)*48.); if(max_ogg_delay<0||max_ogg_delay>48000){ fprintf(stderr,"Invalid max-delay: %s\n",optarg); fprintf(stderr,"max-delay 0-1000 ms.\n"); return 0;//exit(1); } }else if(strcmp(long_options[option_index].name,"serial")==0){ serialno=atoi(optarg); }else if(strcmp(long_options[option_index].name,"set-ctl-int")==0){ int len=strlen(optarg),target; char *spos,*tpos; spos=strchr(optarg,'='); if(len<3||spos==NULL||(spos-optarg)<1||(spos-optarg)>=len){ fprintf(stderr, "Invalid set-ctl-int: %s\n", optarg); fprintf(stderr, "Syntax is --set-ctl-int intX=intY or\n"); fprintf(stderr, "Syntax is --set-ctl-int intS:intX=intY\n"); return 0;//exit(1); } tpos=strchr(optarg,':'); if(tpos==NULL){ target=-1; tpos=optarg-1; }else target=atoi(optarg); if((atoi(tpos+1)&1)!=0){ fprintf(stderr, "Invalid set-ctl-int: %s\n", optarg); fprintf(stderr, "libopus set CTL values are even.\n"); return 0;//exit(1); } if(opt_ctls==0)opt_ctls_ctlval=malloc(sizeof(int)*3); else opt_ctls_ctlval=realloc(opt_ctls_ctlval,sizeof(int)*(opt_ctls+1)*3); opt_ctls_ctlval[opt_ctls*3]=target; opt_ctls_ctlval[opt_ctls*3+1]=atoi(tpos+1); opt_ctls_ctlval[opt_ctls*3+2]=atoi(spos+1); opt_ctls++; }else if(strcmp(long_options[option_index].name,"save-range")==0){ frange=fopen_utf8(optarg,"w"); save_cmd=0; if(frange==NULL){ perror(optarg); fprintf(stderr,"Could not open save-range file: %s\n",optarg); fprintf(stderr,"Must provide a writable file name.\n"); return 0;//exit(1); } range_file=optarg; }else if(strcmp(long_options[option_index].name,"comment")==0){ save_cmd=0; if(!strchr(optarg,'=')){ fprintf(stderr, "Invalid comment: %s\n", optarg); fprintf(stderr, "Comments must be of the form name=value\n"); return 0;//exit(1); } comment_add(&inopt.comments, &inopt.comments_length, NULL, optarg); }else if(strcmp(long_options[option_index].name,"artist")==0){ save_cmd=0; comment_add(&inopt.comments, &inopt.comments_length, "artist", optarg); } else if(strcmp(long_options[option_index].name,"title")==0){ save_cmd=0; comment_add(&inopt.comments, &inopt.comments_length, "title", optarg); } else if(strcmp(long_options[option_index].name,"album")==0){ save_cmd=0; comment_add(&inopt.comments, &inopt.comments_length, "album", optarg); } else if(strcmp(long_options[option_index].name,"date")==0){ save_cmd=0; comment_add(&inopt.comments, &inopt.comments_length, "date", optarg); } else if(strcmp(long_options[option_index].name,"genre")==0){ save_cmd=0; comment_add(&inopt.comments, &inopt.comments_length, "genre", optarg); } else if(strcmp(long_options[option_index].name,"picture")==0){ const char *error_message; char *picture_data; save_cmd=0; picture_data=parse_picture_specification(optarg,&error_message, &seen_file_icons); if(picture_data==NULL){ fprintf(stderr,"Error parsing picture option: %s\n",error_message); return 0;//exit(1); } comment_add(&inopt.comments,&inopt.comments_length, "METADATA_BLOCK_PICTURE",picture_data); free(picture_data); } else if(strcmp(long_options[option_index].name,"padding")==0){ comment_padding=atoi(optarg); } else if(strcmp(long_options[option_index].name,"discard-comments")==0){ inopt.copy_comments=0; inopt.copy_pictures=0; } else if(strcmp(long_options[option_index].name,"discard-pictures")==0){ inopt.copy_pictures=0; } /*Commands whos arguments would leak file paths or just end up as metadata should have save_cmd=0; to prevent them from being saved in the command-line tag.*/ break; case 'h': usage(); return 0;//exit(0); break; case 'V': opustoolsversion(opus_version); return 0;//exit(0); break; case '?': usage(); return 0;//exit(1); break; } if(save_cmd && cline_size<(int)sizeof(ENCODER_string)){ ret=snprintf(&ENCODER_string[cline_size], sizeof(ENCODER_string)-cline_size, "%s--%s",cline_size==0?"":" ",long_options[option_index].name); if(ret<0||ret>=((int)sizeof(ENCODER_string)-cline_size)){ cline_size=sizeof(ENCODER_string); } else { cline_size+=ret; if(optarg){ ret=snprintf(&ENCODER_string[cline_size], sizeof(ENCODER_string)-cline_size, " %s",optarg); if(ret<0||ret>=((int)sizeof(ENCODER_string)-cline_size)){ cline_size=sizeof(ENCODER_string); } else { cline_size+=ret; } } } } } if(argc_utf8-optind!=2){ usage(); return 0;//exit(1); } inFile=argv_utf8[optind]; outFile=argv_utf8[optind+1]; if(cline_size>0)comment_add(&inopt.comments, &inopt.comments_length, "ENCODER_OPTIONS", ENCODER_string); if(strcmp(inFile, "-")==0){ #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdin), _O_BINARY); #elif defined OS2 _fsetmode(stdin,"b"); #endif fin=stdin; }else{ fin=fopen_utf8(inFile, "rb"); if(!fin){ perror(inFile); return 0;//exit(1); } } if(inopt.rawmode){ in_format = &raw_format; in_format->open_func(fin, &inopt, NULL, 0); }else in_format=open_audio_file(fin,&inopt); if(!in_format){ fprintf(stderr,"Error parsing input file: %s\n",inFile); return 0;//exit(1); } if(downmix==0&&inopt.channels>2&&bitrate>0&&bitrate<(16000*inopt.channels)){ if(!quiet)fprintf(stderr,"Notice: Surround bitrate less than 16kbit/sec/channel, downmixing.\n"); downmix=inopt.channels>8?1:2; } if(downmix>0&&downmix<inopt.channels)downmix=setup_downmix(&inopt,downmix); else downmix=0; rate=inopt.rate; chan=inopt.channels; inopt.skip=0; /*In order to code the complete length we'll need to do a little padding*/ setup_padder(&inopt,&original_samples); if(rate>24000)coding_rate=48000; else if(rate>16000)coding_rate=24000; else if(rate>12000)coding_rate=16000; else if(rate>8000)coding_rate=12000; else coding_rate=8000; frame_size=frame_size/(48000/coding_rate); /*Scale the resampler complexity, but only for 48000 output because the near-cutoff behavior matters a lot more at lower rates.*/ //if(rate!=coding_rate)setup_resample(&inopt,coding_rate==48000?(complexity+1)/2:5,coding_rate); if(rate!=coding_rate&&complexity!=10&&!quiet){ fprintf(stderr,"Notice: Using resampling with complexity<10.\n"); fprintf(stderr,"Opusenc is fastest with 48, 24, 16, 12, or 8kHz input.\n\n"); } /*OggOpus headers*/ /*FIXME: broke forcemono*/ header.channels=chan; header.channel_mapping=header.channels>8?255:chan>2; header.input_sample_rate=rate; header.gain=inopt.gain; /*Initialize OPUS encoder*/ /*Framesizes <10ms can only use the MDCT modes, so we switch on RESTRICTED_LOWDELAY to save the extra 2.5ms of codec lookahead when we'll be using only small frames.*/ st=opus_multistream_surround_encoder_create(coding_rate, chan, header.channel_mapping, &header.nb_streams, &header.nb_coupled, header.stream_map, frame_size<480/(48000/coding_rate)?OPUS_APPLICATION_RESTRICTED_LOWDELAY:OPUS_APPLICATION_AUDIO, &ret); if(ret!=OPUS_OK){ fprintf(stderr, "Error cannot create encoder: %s\n", opus_strerror(ret)); return 0;//exit(1); } min_bytes=max_frame_bytes=(1275*3+7)*header.nb_streams; packet=malloc(sizeof(unsigned char)*max_frame_bytes); if(packet==NULL){ fprintf(stderr,"Error allocating packet buffer.\n"); return 0;//exit(1); } if(bitrate<0){ /*Lower default rate for sampling rates [8000-44100) by a factor of (rate+16k)/(64k)*/ bitrate=((64000*header.nb_streams+32000*header.nb_coupled)* (IMIN(48,IMAX(8,((rate<44100?rate:48000)+1000)/1000))+16)+32)>>6; }
static void ogg_init () { int serialno; struct OpusHeadPacket headpacket; struct OpusCommentsPacket *commentspacket; size_t commentspacket_len; serialno = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 0x7FFFFFFF); /*Initialize Ogg stream struct*/ if (-1 == ogg_stream_init (&os, serialno)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("ogg_stream_init() failed.\n")); exit (3); } packet_id = 0; /*Write header*/ { ogg_packet op; ogg_page og; const char *opusver; int vendor_length; memcpy (headpacket.magic, "OpusHead", 8); headpacket.version = 1; headpacket.channels = CHANNELS; headpacket.preskip = GNUNET_htole16 (0); headpacket.sampling_rate = GNUNET_htole32 (SAMPLING_RATE); headpacket.gain = GNUNET_htole16 (0); headpacket.channel_mapping = 0; /* Mono or stereo */ op.packet = (unsigned char *) &headpacket; op.bytes = sizeof (headpacket); op.b_o_s = 1; op.e_o_s = 0; op.granulepos = 0; op.packetno = packet_id++; ogg_stream_packetin (&os, &op); /* Head packet must be alone on its page */ while (ogg_stream_flush (&os, &og)) { write_page (&og); } commentspacket_len = sizeof (*commentspacket); opusver = opus_get_version_string (); vendor_length = strlen (opusver); commentspacket_len += vendor_length; commentspacket_len += sizeof (uint32_t); commentspacket = (struct OpusCommentsPacket *) malloc (commentspacket_len); if (NULL == commentspacket) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to allocate %d bytes for second packet\n"), commentspacket_len); exit (5); } memcpy (commentspacket->magic, "OpusTags", 8); commentspacket->vendor_length = GNUNET_htole32 (vendor_length); memcpy (&commentspacket[1], opusver, vendor_length); *(uint32_t *) &((char *) &commentspacket[1])[vendor_length] = \ GNUNET_htole32 (0); /* no tags */ op.packet = (unsigned char *) commentspacket; op.bytes = commentspacket_len; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = packet_id++; ogg_stream_packetin (&os, &op); /* Comment packets must not be mixed with audio packets on their pages */ while (ogg_stream_flush (&os, &og)) { write_page (&og); } free (commentspacket); } }