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++; } }
int opus_write_header(uint8_t **p_extra, int *i_extra, OpusHeader *header) { unsigned char header_data[100]; const int packet_size = opus_header_to_packet(header, header_data, sizeof(header_data)); ogg_packet headers[2]; headers[0].packet = header_data; headers[0].bytes = packet_size; headers[0].b_o_s = 1; headers[0].e_o_s = 0; headers[0].granulepos = 0; headers[0].packetno = 0; size_t comments_length; char *comments = comment_init(&comments_length); if (!comments) return 1; if (comment_add(&comments, &comments_length, "ENCODER=", "VLC media player")) { free(comments); return 1; } if (comment_pad(&comments, &comments_length)) { free(comments); return 1; } headers[1].packet = (unsigned char *) comments; headers[1].bytes = comments_length; headers[1].b_o_s = 0; headers[1].e_o_s = 0; headers[1].granulepos = 0; headers[1].packetno = 1; for (unsigned i = 0; i < ARRAY_SIZE(headers); ++i) { if (xiph_AppendHeaders(i_extra, (void **) p_extra, headers[i].bytes, headers[i].packet)) { *i_extra = 0; *p_extra = NULL; } } return 0; }
/* Eats characters until '\n' and adds them to the comment. */ static void eat_comment_line () { for (;;) { int c = phase1_getc (); if (c == '\n' || c == EOF) { comment_line_end (0); break; } if (!(buflen == 0 && (c == ' ' || c == '\t'))) comment_add (c); } }
int opus_write_header(uint8_t **p_extra, int *i_extra, OpusHeader *header, const char *vendor) { unsigned char header_data[100]; const int packet_size = opus_header_to_packet(header, header_data, sizeof(header_data)); unsigned char *data[2]; size_t size[2]; data[0] = header_data; size[0] = packet_size; size_t comments_length; char *comments = comment_init(&comments_length, vendor); if (!comments) return 1; if (comment_add(&comments, &comments_length, "ENCODER=", "VLC media player")) { free(comments); return 1; } if (comment_pad(&comments, &comments_length)) { free(comments); return 1; } data[1] = (unsigned char *) comments; size[1] = comments_length; for (unsigned i = 0; i < ARRAY_SIZE(data); ++i) if (xiph_AppendHeaders(i_extra, (void **) p_extra, size[i], data[i])) { *i_extra = 0; *p_extra = NULL; } return 0; }
int main(int argc, char **argv) { int nb_samples, total_samples=0, nb_encoded; int c; int option_index = 0; char *inFile, *outFile; FILE *fin, *fout; short input[MAX_FRAME_SIZE]; celt_int32 frame_size = 960; int quiet=0; int nbBytes; CELTMode *mode; void *st; unsigned char bits[MAX_FRAME_BYTES]; int with_cbr = 0; int with_cvbr = 0; int with_skeleton = 0; int total_bytes = 0; int peak_bytes = 0; struct option long_options[] = { {"bitrate", required_argument, NULL, 0}, {"cbr",no_argument,NULL, 0}, {"cvbr",no_argument,NULL, 0}, {"comp", required_argument, NULL, 0}, {"nopf", no_argument, NULL, 0}, {"independent", no_argument, NULL, 0}, {"framesize", required_argument, NULL, 0}, {"skeleton",no_argument,NULL, 0}, {"help", no_argument, NULL, 0}, {"quiet", no_argument, NULL, 0}, {"le", no_argument, NULL, 0}, {"be", no_argument, NULL, 0}, {"8bit", no_argument, NULL, 0}, {"16bit", no_argument, NULL, 0}, {"mono", no_argument, NULL, 0}, {"stereo", 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}, {"author", required_argument, NULL, 0}, {"title", required_argument, NULL, 0}, {0, 0, 0, 0} }; int print_bitrate=0; celt_int32 rate=48000; celt_int32 size; int chan=1; int fmt=16; int lsb=1; ogg_stream_state os; ogg_stream_state so; /* ogg stream for skeleton bitstream */ ogg_page og; ogg_packet op; int bytes_written=0, ret, result; int id=-1; CELTHeader header; char vendor_string[64]; char *comments; int comments_length; int close_in=0, close_out=0; int eos=0; float bitrate=-1; char first_bytes[12]; int wave_input=0; celt_int32 lookahead = 0; int bytes_per_packet=-1; int complexity=-127; int prediction=2; /*Process command-line options*/ while(1) { c = getopt_long (argc, argv, "hvV", long_options, &option_index); if (c==-1) break; switch(c) { case 0: if (strcmp(long_options[option_index].name,"bitrate")==0) { bitrate = atof (optarg); } else if (strcmp(long_options[option_index].name,"cbr")==0) { with_cbr=1; } else if (strcmp(long_options[option_index].name,"cvbr")==0) { with_cvbr=1; } else if (strcmp(long_options[option_index].name,"skeleton")==0) { with_skeleton=1; } else if (strcmp(long_options[option_index].name,"help")==0) { usage(); exit(0); } else if (strcmp(long_options[option_index].name,"quiet")==0) { quiet = 1; } else if (strcmp(long_options[option_index].name,"version")==0) { version(); exit(0); } else if (strcmp(long_options[option_index].name,"version-short")==0) { version_short(); exit(0); } else if (strcmp(long_options[option_index].name,"le")==0) { lsb=1; } else if (strcmp(long_options[option_index].name,"be")==0) { lsb=0; } else if (strcmp(long_options[option_index].name,"8bit")==0) { fmt=8; } else if (strcmp(long_options[option_index].name,"16bit")==0) { fmt=16; } else if (strcmp(long_options[option_index].name,"stereo")==0) { chan=2; } else if (strcmp(long_options[option_index].name,"mono")==0) { chan=1; } else if (strcmp(long_options[option_index].name,"rate")==0) { rate=atoi (optarg); } else if (strcmp(long_options[option_index].name,"comp")==0) { complexity=atoi (optarg); } else if (strcmp(long_options[option_index].name,"framesize")==0) { frame_size=atoi (optarg); } else if (strcmp(long_options[option_index].name,"nopf")==0) { if (prediction>1) prediction=1; } else if (strcmp(long_options[option_index].name,"independent")==0) { prediction=0; } else if (strcmp(long_options[option_index].name,"comment")==0) { if (!strchr(optarg, '=')) { fprintf (stderr, "Invalid comment: %s\n", optarg); fprintf (stderr, "Comments must be of the form name=value\n"); exit(1); } comment_add(&comments, &comments_length, NULL, optarg); } else if (strcmp(long_options[option_index].name,"author")==0) { comment_add(&comments, &comments_length, "author=", optarg); } else if (strcmp(long_options[option_index].name,"title")==0) { comment_add(&comments, &comments_length, "title=", optarg); } break; case 'h': usage(); exit(0); break; case 'v': version(); exit(0); break; case 'V': print_bitrate=1; break; case '?': usage(); exit(1); break; } } if (argc-optind!=2) { usage(); exit(1); } inFile=argv[optind]; outFile=argv[optind+1]; /*Initialize Ogg stream struct*/ srand(time(NULL)); if (ogg_stream_init(&os, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } if (with_skeleton && ogg_stream_init(&so, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } 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(inFile, "rb"); if (!fin) { perror(inFile); exit(1); } close_in=1; } { fread(first_bytes, 1, 12, fin); if (strncmp(first_bytes,"RIFF",4)==0 && strncmp(first_bytes,"RIFF",4)==0) { if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1) exit(1); wave_input=1; lsb=1; /* CHECK: exists big-endian .wav ?? */ } } if (bitrate<=0.005) if (chan==1) bitrate=64.0; else bitrate=128.0; bytes_per_packet = MAX_FRAME_BYTES; mode = celt_mode_create(rate, frame_size, NULL); if (!mode) return 1; snprintf(vendor_string, sizeof(vendor_string), "Encoded with CELT %s\n",CELT_VERSION); comment_init(&comments, &comments_length, vendor_string); /*celt_mode_info(mode, CELT_GET_FRAME_SIZE, &frame_size);*/ celt_header_init(&header, mode, frame_size, chan); header.nb_channels = chan; { char *st_string="mono"; if (chan==2) st_string="stereo"; if (!quiet) if (with_cbr) fprintf (stderr, "Encoding %.0f kHz %s audio in %.0fms packets at %0.3fkbit/sec (%d bytes per packet, CBR)\n", header.sample_rate/1000., st_string, frame_size/(float)header.sample_rate*1000., bitrate, bytes_per_packet); else fprintf (stderr, "Encoding %.0f kHz %s audio in %.0fms packets at %0.3fkbit/sec (%d bytes per packet maximum)\n", header.sample_rate/1000., st_string, frame_size/(float)header.sample_rate*1000., bitrate, bytes_per_packet); } /*Initialize CELT encoder*/ st = celt_encoder_create_custom(mode, chan, NULL); { int tmp = (bitrate*1000); if (celt_encoder_ctl(st, CELT_SET_BITRATE(tmp)) != CELT_OK) { fprintf (stderr, "bitrate request failed\n"); return 1; } } if (!with_cbr) { if (celt_encoder_ctl(st, CELT_SET_VBR(1)) != CELT_OK) { fprintf (stderr, "VBR request failed\n"); return 1; } if (!with_cvbr) { if (celt_encoder_ctl(st, CELT_SET_VBR_CONSTRAINT(0)) != CELT_OK) { fprintf (stderr, "VBR constraint failed\n"); return 1; } } } if (celt_encoder_ctl(st, CELT_SET_PREDICTION(prediction)) != CELT_OK) { fprintf (stderr, "Prediction request failed\n"); return 1; } if (complexity!=-127) { if (celt_encoder_ctl(st, CELT_SET_COMPLEXITY(complexity)) != CELT_OK) { fprintf (stderr, "Only complexity 0 through 10 is supported\n"); return 1; } } if (strcmp(outFile,"-")==0) { #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif fout=stdout; } else { fout = fopen(outFile, "wb"); if (!fout) { perror(outFile); exit(1); } close_out=1; } if (with_skeleton) { fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n"); } /* first packet should be the skeleton header. */ if (with_skeleton) { add_fishead_packet(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n"); exit(1); } else bytes_written += ret; } /*Write header*/ { unsigned char header_data[100]; int packet_size = celt_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; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } op.packet = (unsigned char *)comments; op.bytes = comments_length; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = 1; ogg_stream_packetin(&os, &op); } /* fisbone packet should be write after all bos pages */ if (with_skeleton) { add_fisbone_packet(&so, os.serialno, &header); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n"); exit(1); } else bytes_written += ret; } /* writing the rest of the celt header packets */ while((result = ogg_stream_flush(&os, &og))) { if(!result) break; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } free(comments); /* write the skeleton eos packet */ if (with_skeleton) { add_eos_packet_to_stream(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton header to output stream\n"); exit(1); } else bytes_written += ret; } if (!wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } if (nb_samples==0) eos=1; total_samples += nb_samples; nb_encoded = -lookahead; /*Main encoding loop (one frame per iteration)*/ while (!eos || total_samples>nb_encoded) { id++; /*Encode current frame*/ nbBytes = celt_encode(st, input, frame_size, bits, bytes_per_packet); if (nbBytes<0) { fprintf(stderr, "Got error %d while encoding. Aborting.\n", nbBytes); break; } nb_encoded += frame_size; total_bytes += nbBytes; peak_bytes=IMAX(nbBytes,peak_bytes); if (wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL); } if (nb_samples==0) { eos=1; } if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; total_samples += nb_samples; op.packet = (unsigned char *)bits; op.bytes = nbBytes; op.b_o_s = 0; /*Is this redundent?*/ if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; op.granulepos = (id+1)*frame_size-lookahead; if (op.granulepos>total_samples) op.granulepos = total_samples; /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/ op.packetno = 2+id; ogg_stream_packetin(&os, &op); /*Write all new pages (most likely 0 or 1)*/ while (ogg_stream_pageout(&os,&og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } } /*Flush all pages left to be written*/ while (ogg_stream_flush(&os, &og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } if (!with_cbr && !quiet) fprintf (stderr, "Average rate %0.3fkbit/sec, %d peak bytes per packet\n", (total_bytes*8.0/((float)nb_encoded/header.sample_rate))/1000.0, peak_bytes); celt_encoder_destroy(st); celt_mode_destroy(mode); ogg_stream_clear(&os); if (close_in) fclose(fin); if (close_out) fclose(fout); return 0; }
/*Callback to process a metadata packet.*/ static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata,void *client_data){ flacfile *flac; oe_enc_opt *inopt; (void)decoder; flac=(flacfile *)client_data; inopt=flac->inopt; switch(metadata->type){ case FLAC__METADATA_TYPE_STREAMINFO: flac->max_blocksize=metadata->data.stream_info.max_blocksize; inopt->rate=metadata->data.stream_info.sample_rate; inopt->channels=flac->channels=metadata->data.stream_info.channels; inopt->samplesize=metadata->data.stream_info.bits_per_sample; inopt->total_samples_per_channel= metadata->data.stream_info.total_samples; flac->block_buf=malloc( flac->max_blocksize*flac->channels*sizeof(*flac->block_buf)); flac->block_buf_pos=0; flac->block_buf_len=0; break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: { FLAC__StreamMetadata_VorbisComment_Entry *comments; FLAC__uint32 num_comments; FLAC__uint32 i; double reference_loudness; double album_gain; double track_gain; double gain; int saw_album_gain; int saw_track_gain; char *saved_locale; if(!inopt->copy_comments)break; num_comments=metadata->data.vorbis_comment.num_comments; comments=metadata->data.vorbis_comment.comments; saw_album_gain=saw_track_gain=0; album_gain=track_gain=0; /*The default reference loudness for ReplayGain is 89.0 dB*/ reference_loudness=89; /*The code below uses strtod for the gain tags, so make sure the locale is C*/ saved_locale=setlocale(LC_NUMERIC,"C"); for(i=0;i<num_comments;i++){ char *entry; char *end; entry=(char *)comments[i].entry; /*Check for ReplayGain tags. Parse the ones we have R128 equivalents for, and skip the others.*/ if(oi_strncasecmp(entry,"REPLAYGAIN_REFERENCE_LOUDNESS=",30)==0){ gain=strtod(entry+30,&end); if(end<=entry+30){ fprintf(stderr,_("WARNING: Invalid ReplayGain tag: %s\n"),entry); } else reference_loudness=gain; continue; } if(oi_strncasecmp(entry,"REPLAYGAIN_ALBUM_GAIN=",22)==0){ gain=strtod(entry+22,&end); if(end<=entry+22){ fprintf(stderr,_("WARNING: Invalid ReplayGain tag: %s\n"),entry); } else{ album_gain=gain; saw_album_gain=1; } continue; } if(oi_strncasecmp(entry,"REPLAYGAIN_TRACK_GAIN=",22)==0){ gain=strtod(entry+22,&end); if(end<entry+22){ fprintf(stderr,_("WARNING: Invalid ReplayGain tag: %s\n"),entry); } else{ track_gain=gain; saw_track_gain=1; } continue; } if(oi_strncasecmp(entry,"REPLAYGAIN_ALBUM_PEAK=",22)==0 ||oi_strncasecmp(entry,"REPLAYGAIN_TRACK_PEAK=",22)==0){ continue; } if(!strchr(entry,'=')){ fprintf(stderr,_("WARNING: Invalid comment: %s\n"),entry); fprintf(stderr, _("Discarding comment not in the form name=value\n")); continue; } comment_add(&inopt->comments,&inopt->comments_length,NULL,entry); } setlocale(LC_NUMERIC,saved_locale); /*Set the header gain to the album gain after converting to the R128 reference level.*/ if(saw_album_gain){ gain=256*(album_gain+(84-reference_loudness))+0.5; inopt->gain=gain<-32768?-32768:gain<32767?(int)floor(gain):32767; } /*If there was a track gain, then add an equivalent R128 tag for that.*/ if(saw_track_gain){ char track_gain_buf[7]; int track_gain_val; gain=256*(track_gain-album_gain)+0.5; track_gain_val=gain<-32768?-32768:gain<32767?(int)floor(gain):32767; sprintf(track_gain_buf,"%i",track_gain_val); comment_add(&inopt->comments,&inopt->comments_length, "R128_TRACK_GAIN",track_gain_buf); } } break; case FLAC__METADATA_TYPE_PICTURE: { char *buf; char *b64; size_t mime_type_length; size_t description_length; size_t buf_sz; size_t b64_sz; size_t offs; mime_type_length=strlen(metadata->data.picture.mime_type); description_length=strlen((char *)metadata->data.picture.description); buf_sz=32+mime_type_length+description_length +metadata->data.picture.data_length; buf=(char *)malloc(buf_sz); offs=0; WRITE_U32_BE(buf+offs,metadata->data.picture.type); offs+=4; WRITE_U32_BE(buf+offs,(FLAC__uint32)mime_type_length); offs+=4; memcpy(buf+offs,metadata->data.picture.mime_type,mime_type_length); offs+=mime_type_length; WRITE_U32_BE(buf+offs,(FLAC__uint32)description_length); offs+=4; memcpy(buf+offs,metadata->data.picture.description,description_length); offs+=description_length; WRITE_U32_BE(buf+offs,metadata->data.picture.width); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.height); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.depth); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.colors); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.data_length); offs+=4; memcpy(buf+offs,metadata->data.picture.data, metadata->data.picture.data_length); b64_sz=BASE64_LENGTH(buf_sz)+1; b64=(char *)malloc(b64_sz); base64_encode(b64,buf,buf_sz); free(buf); comment_add(&inopt->comments,&inopt->comments_length, "METADATA_BLOCK_PICTURE",b64); free(b64); } break; default: break; } }
static int phase2_getc () { int c; bool last_was_star; c = phase1_getc (); if (c != '/') return c; c = phase1_getc (); switch (c) { default: phase1_ungetc (c); return '/'; case '*': /* C comment. */ comment_start (); last_was_star = false; for (;;) { c = phase1_getc (); if (c == EOF) break; /* We skip all leading white space, but not EOLs. */ if (!(buflen == 0 && (c == ' ' || c == '\t'))) comment_add (c); switch (c) { case '\n': comment_line_end (1); comment_start (); last_was_star = false; continue; case '*': last_was_star = true; continue; case '/': if (last_was_star) { comment_line_end (2); break; } /* FALLTHROUGH */ default: last_was_star = false; continue; } break; } last_comment_line = line_number; return ' '; case '/': /* C++ or ISO C 99 comment. */ comment_start (); for (;;) { c = phase1_getc (); if (c == '\n' || c == EOF) break; /* We skip all leading white space, but not EOLs. */ if (!(buflen == 0 && (c == ' ' || c == '\t'))) comment_add (c); } comment_line_end (0); last_comment_line = line_number; return '\n'; } }
/* * Create opus writer port. */ PJ_DEF(pj_status_t) pjmedia_opus_writer_port_create( pj_pool_t *pool, const char *filename, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned flags, pj_ssize_t buff_size, pjmedia_port **p_port ) { struct opus_port *oport; struct opus_tool_param *otp; pj_str_t name; pj_status_t status; pjmedia_frame tempframe; int i,ret; /* Check arguments. */ PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL); /* Only supports 16bits per sample for now. */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); /* Create file port instance. */ oport = PJ_POOL_ZALLOC_T(pool, struct opus_port); PJ_ASSERT_RETURN(oport != NULL, PJ_ENOMEM); /* Initialize port info. */ pj_strdup2(pool, &name, filename); pjmedia_port_info_init(&oport->base.info, &name, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame); oport->base.get_frame = &opus_get_frame; oport->base.put_frame = &opus_put_frame; oport->base.on_destroy = &opus_on_destroy; oport->bytes_per_sample = 2; /********************** * opus-tool Start *********************/ otp = PJ_POOL_ZALLOC_T(pool, struct opus_tool_param); PJ_ASSERT_RETURN(otp != NULL, PJ_ENOMEM); /* Initialize some default parameters. */ otp->opt_ctls_ctlval=NULL; otp->frange=NULL; otp->range_file=NULL; otp->inopt.channels=channel_count; otp->inopt.rate=otp->coding_rate=otp->rate=sampling_rate; /* Some default value */ otp->frame_size=960; otp->bitrate=-1; otp->with_hard_cbr=0; otp->with_cvbr=0; otp->complexity=10; otp->expect_loss=0; otp->lookahead=0; otp->bytes_written=0; otp->pages_out=0; otp->comment_padding=512; otp->eos=0; otp->nb_samples=-1; otp->id=-1; otp->nb_encoded=0; otp->enc_granulepos=0; otp->total_bytes=0; otp->peak_bytes=0; otp->max_ogg_delay=48000; /* 0 dB gain is recommended unless you know what you're doing */ otp->inopt.gain=0; otp->inopt.samplesize=(oport->bytes_per_sample)*8; otp->inopt.endianness=0; otp->inopt.rawmode=0; otp->inopt.ignorelength=0; otp->inopt.copy_comments=1; otp->inopt.skip=0; otp->start_time = time(NULL); srand(((_getpid()&65535)<<15)^(otp->start_time)); otp->serialno=rand(); otp->opus_version="libopus 1.0.3"; /* Vendor string should just be the encoder library, the ENCODER comment specifies the tool used. */ comment_init(&otp->inopt.comments, &otp->inopt.comments_length, otp->opus_version); snprintf(otp->ENCODER_string, sizeof(otp->ENCODER_string), "opusenc from %s %s", PACKAGE_NAME, PACKAGE_VERSION); comment_add(&otp->inopt.comments, &otp->inopt.comments_length, "ENCODER", otp->ENCODER_string); otp->outFile=(char *)filename; otp->rate=otp->inopt.rate; otp->chan=otp->inopt.channels; otp->inopt.skip=0; if(otp->rate>24000)otp->coding_rate=48000; else if(otp->rate>16000)otp->coding_rate=24000; else if(otp->rate>12000)otp->coding_rate=16000; else if(otp->rate>8000)otp->coding_rate=12000; else otp->coding_rate=8000; otp->frame_size=otp->frame_size/(48000/otp->coding_rate); /*OggOpus headers*/ /*FIXME: broke forcemono*/ otp->header.channels=otp->chan; otp->header.channel_mapping=otp->header.channels>8?255:otp->chan>2; otp->header.input_sample_rate=otp->rate; otp->header.gain=otp->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. */ otp->st=opus_multistream_surround_encoder_create(otp->coding_rate, otp->chan, otp->header.channel_mapping, &otp->header.nb_streams, &otp->header.nb_coupled, otp->header.stream_map, otp->frame_size<480/(48000/otp->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)); exit(1); } otp->min_bytes=otp->max_frame_bytes=(1275*3+7)*otp->header.nb_streams; otp->packet=(unsigned char*)malloc(sizeof(unsigned char)*otp->max_frame_bytes); if(otp->packet==NULL) { fprintf(stderr, "Error allocating packet buffer.\n"); exit(1); } if(otp->bitrate<0) { /* Lower default rate for sampling rates [8000-44100) by a factor of (rate+16k)/(64k) */ otp->bitrate=((64000*otp->header.nb_streams+32000*otp->header.nb_coupled)* (IMIN(48,IMAX(8,((otp->rate<44100?otp->rate:48000)+1000)/1000))+16)+32)>>6; }
int main(int argc, char **argv) { int nb_samples, total_samples=0, nb_encoded; int c; int option_index = 0; char *inFile, *outFile; FILE *fin, *fout; short input[MAX_FRAME_SIZE]; celt_int32_t frame_size; int quiet=0; int nbBytes; CELTMode *mode; void *st; unsigned char bits[MAX_FRAME_BYTES]; int with_skeleton = 0; struct option long_options[] = { {"bitrate", required_argument, NULL, 0}, {"comp", required_argument, NULL, 0}, {"skeleton",no_argument,NULL, 0}, {"help", no_argument, NULL, 0}, {"quiet", no_argument, NULL, 0}, {"le", no_argument, NULL, 0}, {"be", no_argument, NULL, 0}, {"8bit", no_argument, NULL, 0}, {"16bit", no_argument, NULL, 0}, {"mono", no_argument, NULL, 0}, {"stereo", 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}, {"author", required_argument, NULL, 0}, {"title", required_argument, NULL, 0}, {0, 0, 0, 0} }; int print_bitrate=0; celt_int32_t rate=44100; celt_int32_t size; int chan=1; int fmt=16; int lsb=1; ogg_stream_state os; ogg_stream_state so; /* ogg stream for skeleton bitstream */ ogg_page og; ogg_packet op; int bytes_written=0, ret, result; int id=-1; CELT051Header header; char vendor_string[64]; char *comments; int comments_length; int close_in=0, close_out=0; int eos=0; celt_int32_t bitrate=-1; char first_bytes[12]; int wave_input=0; celt_int32_t lookahead = 0; int bytes_per_packet=48; int complexity=-127; snprintf(vendor_string, sizeof(vendor_string), "Encoded with CELT\n"); comment_init(&comments, &comments_length, vendor_string); /*Process command-line options*/ while(1) { c = getopt_long (argc, argv, "hvV", long_options, &option_index); if (c==-1) break; switch(c) { case 0: if (strcmp(long_options[option_index].name,"bitrate")==0) { bitrate = atoi (optarg); } else if (strcmp(long_options[option_index].name,"skeleton")==0) { with_skeleton=1; } else if (strcmp(long_options[option_index].name,"help")==0) { usage(); exit(0); } else if (strcmp(long_options[option_index].name,"quiet")==0) { quiet = 1; } else if (strcmp(long_options[option_index].name,"version")==0) { version(); exit(0); } else if (strcmp(long_options[option_index].name,"version-short")==0) { version_short(); exit(0); } else if (strcmp(long_options[option_index].name,"le")==0) { lsb=1; } else if (strcmp(long_options[option_index].name,"be")==0) { lsb=0; } else if (strcmp(long_options[option_index].name,"8bit")==0) { fmt=8; } else if (strcmp(long_options[option_index].name,"16bit")==0) { fmt=16; } else if (strcmp(long_options[option_index].name,"stereo")==0) { chan=2; } else if (strcmp(long_options[option_index].name,"mono")==0) { chan=1; } else if (strcmp(long_options[option_index].name,"rate")==0) { rate=atoi (optarg); } else if (strcmp(long_options[option_index].name,"comp")==0) { complexity=atoi (optarg); } else if (strcmp(long_options[option_index].name,"comment")==0) { if (!strchr(optarg, '=')) { fprintf (stderr, "Invalid comment: %s\n", optarg); fprintf (stderr, "Comments must be of the form name=value\n"); exit(1); } comment_add(&comments, &comments_length, NULL, optarg); } else if (strcmp(long_options[option_index].name,"author")==0) { comment_add(&comments, &comments_length, "author=", optarg); } else if (strcmp(long_options[option_index].name,"title")==0) { comment_add(&comments, &comments_length, "title=", optarg); } break; case 'h': usage(); exit(0); break; case 'v': version(); exit(0); break; case 'V': print_bitrate=1; break; case '?': usage(); exit(1); break; } } fprintf(stderr,"\nWARNING: This encoder is a CELT *PRERELEASE*. It produces streams that are\n" " not decodable by ANY OTHER VERSION. These streams will NOT be\n" " supported or decodable by any future CELT release.\n\n"); if (argc-optind!=2) { usage(); exit(1); } inFile=argv[optind]; outFile=argv[optind+1]; /*Initialize Ogg stream struct*/ srand(time(NULL)); if (ogg_stream_init(&os, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } if (with_skeleton && ogg_stream_init(&so, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } 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(inFile, "rb"); if (!fin) { perror(inFile); exit(1); } close_in=1; } { fread(first_bytes, 1, 12, fin); if (strncmp(first_bytes,"RIFF",4)==0 && strncmp(first_bytes,"RIFF",4)==0) { if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1) exit(1); wave_input=1; lsb=1; /* CHECK: exists big-endian .wav ?? */ } } if (chan == 1) { if (bitrate < 0) bitrate = 64; if (bitrate < 32) bitrate = 32; if (bitrate > 110) bitrate = 110; } else if (chan == 2) { if (bitrate < 0) bitrate = 128; if (bitrate < 64) bitrate = 64; if (bitrate > 150) bitrate = 150; } else { fprintf (stderr, "Only mono and stereo are supported\n"); return 1; } mode = celt051_mode_create(rate, chan, 256, NULL); if (!mode) return 1; celt051_mode_info(mode, CELT_GET_FRAME_SIZE, &frame_size); bytes_per_packet = (bitrate*1000*frame_size/rate+4)/8; celt051_header_init(&header, mode); header.nb_channels = chan; { char *st_string="mono"; if (chan==2) st_string="stereo"; if (!quiet) fprintf (stderr, "Encoding %d Hz audio using %s (%d bytes per packet)\n", header.sample_rate, st_string, bytes_per_packet); } /*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n", header.rate, mode->bitrate, mode->modeName);*/ /*Initialize CELT encoder*/ st = celt051_encoder_create(mode); if (complexity!=-127) { if (celt051_encoder_ctl(st, CELT_SET_COMPLEXITY(complexity)) != CELT_OK) { fprintf (stderr, "Only complexity 0 through 10 is supported\n"); return 1; } } if (strcmp(outFile,"-")==0) { #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif fout=stdout; } else { fout = fopen(outFile, "wb"); if (!fout) { perror(outFile); exit(1); } close_out=1; } if (with_skeleton) { fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n"); } /* first packet should be the skeleton header. */ if (with_skeleton) { add_fishead_packet(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n"); exit(1); } else bytes_written += ret; } /*Write header*/ { unsigned char header_data[100]; int packet_size = celt051_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; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } op.packet = (unsigned char *)comments; op.bytes = comments_length; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = 1; ogg_stream_packetin(&os, &op); } /* fisbone packet should be write after all bos pages */ if (with_skeleton) { add_fisbone_packet(&so, os.serialno, &header); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n"); exit(1); } else bytes_written += ret; } /* writing the rest of the celt header packets */ while((result = ogg_stream_flush(&os, &og))) { if(!result) break; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } free(comments); /* write the skeleton eos packet */ if (with_skeleton) { add_eos_packet_to_stream(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton header to output stream\n"); exit(1); } else bytes_written += ret; } if (!wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } if (nb_samples==0) eos=1; total_samples += nb_samples; nb_encoded = -lookahead; /*Main encoding loop (one frame per iteration)*/ while (!eos || total_samples>nb_encoded) { id++; /*Encode current frame*/ nbBytes = celt051_encode(st, input, NULL, bits, bytes_per_packet); if (nbBytes<0) { fprintf(stderr, "Got error %d while encoding. Aborting.\n", nbBytes); break; } nb_encoded += frame_size; if (wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL); } if (nb_samples==0) { eos=1; } if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; total_samples += nb_samples; op.packet = (unsigned char *)bits; op.bytes = nbBytes; op.b_o_s = 0; /*Is this redundent?*/ if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; op.granulepos = (id+1)*frame_size-lookahead; if (op.granulepos>total_samples) op.granulepos = total_samples; /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/ op.packetno = 2+id; ogg_stream_packetin(&os, &op); /*Write all new pages (most likely 0 or 1)*/ while (ogg_stream_pageout(&os,&og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } } /*Flush all pages left to be written*/ while (ogg_stream_flush(&os, &og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } celt051_encoder_destroy(st); celt051_mode_destroy(mode); ogg_stream_clear(&os); if (close_in) fclose(fin); if (close_out) fclose(fout); return 0; }
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 int phase3_getc () { int lineno; int c; if (phase3_pushback_length) return phase3_pushback[--phase3_pushback_length]; c = phase1_getc (); if (c == '#') { /* sh comment. */ bool last_was_qmark = false; comment_start (); lineno = line_number; for (;;) { c = phase1_getc (); if (c == '\n' || c == EOF) { comment_line_end (0); break; } if (last_was_qmark && c == '>') { comment_line_end (1); skip_html (); break; } /* We skip all leading white space, but not EOLs. */ if (!(buflen == 0 && (c == ' ' || c == '\t'))) comment_add (c); last_was_qmark = (c == '?' || c == '%'); } last_comment_line = lineno; return '\n'; } else if (c == '/') { c = phase1_getc (); switch (c) { default: phase1_ungetc (c); return '/'; case '*': { /* C comment. */ bool last_was_star; comment_start (); lineno = line_number; last_was_star = false; for (;;) { c = phase1_getc (); if (c == EOF) break; /* We skip all leading white space, but not EOLs. */ if (buflen == 0 && (c == ' ' || c == '\t')) continue; comment_add (c); switch (c) { case '\n': comment_line_end (1); comment_start (); lineno = line_number; last_was_star = false; continue; case '*': last_was_star = true; continue; case '/': if (last_was_star) { comment_line_end (2); break; } /* FALLTHROUGH */ default: last_was_star = false; continue; } break; } last_comment_line = lineno; return ' '; } case '/': { /* C++ comment. */ bool last_was_qmark = false; comment_start (); lineno = line_number; for (;;) { c = phase1_getc (); if (c == '\n' || c == EOF) { comment_line_end (0); break; } if (last_was_qmark && c == '>') { comment_line_end (1); skip_html (); break; } /* We skip all leading white space, but not EOLs. */ if (!(buflen == 0 && (c == ' ' || c == '\t'))) comment_add (c); last_was_qmark = (c == '?' || c == '%'); } last_comment_line = lineno; return '\n'; } } } else return c; }
static void phase2_get (token_ty *tp) { static char *buffer; static int bufmax; int bufpos; int c; if (phase2_pushback_length) { *tp = phase2_pushback[--phase2_pushback_length]; return; } tp->string = NULL; for (;;) { tp->line_number = line_number; c = phase1_getc (); switch (c) { case EOF: tp->type = token_type_eof; return; case '"': { /* Comment. */ int lineno; comment_start (); lineno = line_number; for (;;) { c = phase1_getc (); if (c == '"' || c == EOF) break; if (c == '\n') { comment_line_end (); comment_start (); } else { /* We skip all leading white space, but not EOLs. */ if (!(buflen == 0 && (c == ' ' || c == '\t'))) comment_add (c); } } comment_line_end (); last_comment_line = lineno; continue; } case '\n': if (last_non_comment_line > last_comment_line) savable_comment_reset (); /* FALLTHROUGH */ case ' ': case '\t': case '\r': /* Ignore whitespace. */ continue; } last_non_comment_line = tp->line_number; switch (c) { case '\'': /* String literal. */ bufpos = 0; for (;;) { c = phase1_getc (); if (c == EOF) break; if (c == '\'') { c = phase1_getc (); if (c != '\'') { phase1_ungetc (c); break; } } if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos++] = c; } if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos] = 0; tp->type = token_type_string_literal; tp->string = xstrdup (buffer); return; case '+': case '-': case '*': case '/': case '~': case '|': case ',': case '<': case '>': case '=': case '&': case '@': case '?': case '%': case '\\': { char *name; int c2 = phase1_getc (); switch (c2) { case '+': case '-': case '*': case '/': case '~': case '|': case ',': case '<': case '>': case '=': case '&': case '@': case '?': case '%': name = xmalloc (3); name[0] = c; name[1] = c2; name[2] = '\0'; tp->type = token_type_symbol; tp->string = name; return; default: phase1_ungetc (c2); break; } name = xmalloc (2); name[0] = c; name[1] = '\0'; tp->type = token_type_symbol; tp->string = name; return; } case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': /* Recognize id or id":"[id":"]* or id":"[id":"]*id. */ bufpos = 0; for (;;) { if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos++] = c; c = phase1_getc (); switch (c) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': continue; case ':': if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos++] = c; c = phase1_getc (); switch (c) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': continue; default: phase1_ungetc (c); break; } break; default: phase1_ungetc (c); break; } break; } if (bufpos >= bufmax) { bufmax = 2 * bufmax + 10; buffer = xrealloc (buffer, bufmax); } buffer[bufpos] = '\0'; tp->string = xstrdup (buffer); tp->type = token_type_symbol; return; case '#': /* Uniquification operator. */ tp->type = token_type_uniq; return; case '$': c = phase1_getc (); tp->type = token_type_other; return; default: tp->type = token_type_other; return; } } }
int main(int argc, char **argv) { int nb_samples, total_samples=0, nb_encoded; int c; int option_index = 0; char *inFile, *outFile; FILE *fin, *fout; short input[MAX_FRAME_SIZE]; spx_int32_t frame_size; int quiet=0; spx_int32_t vbr_enabled=0; spx_int32_t vbr_max=0; int abr_enabled=0; spx_int32_t vad_enabled=0; spx_int32_t dtx_enabled=0; int nbBytes; const SpeexMode *mode=NULL; int modeID = -1; void *st; SpeexBits bits; char cbits[MAX_FRAME_BYTES]; int with_skeleton = 0; struct option long_options[] = { {"wideband", no_argument, NULL, 0}, {"ultra-wideband", no_argument, NULL, 0}, {"narrowband", no_argument, NULL, 0}, {"vbr", no_argument, NULL, 0}, {"vbr-max-bitrate", required_argument, NULL, 0}, {"abr", required_argument, NULL, 0}, {"vad", no_argument, NULL, 0}, {"dtx", no_argument, NULL, 0}, {"quality", required_argument, NULL, 0}, {"bitrate", required_argument, NULL, 0}, {"nframes", required_argument, NULL, 0}, {"comp", required_argument, NULL, 0}, #ifdef USE_SPEEXDSP {"denoise", no_argument, NULL, 0}, {"agc", no_argument, NULL, 0}, #endif {"no-highpass", no_argument, NULL, 0}, {"skeleton",no_argument,NULL, 0}, {"help", no_argument, NULL, 0}, {"quiet", no_argument, NULL, 0}, {"le", no_argument, NULL, 0}, {"be", no_argument, NULL, 0}, {"8bit", no_argument, NULL, 0}, {"16bit", no_argument, NULL, 0}, {"stereo", 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}, {"author", required_argument, NULL, 0}, {"title", required_argument, NULL, 0}, {"print-rate", no_argument, NULL, 0}, {0, 0, 0, 0} }; int print_bitrate=0; spx_int32_t rate=0; spx_int32_t size; int chan=1; int fmt=16; spx_int32_t quality=-1; float vbr_quality=-1; int lsb=1; ogg_stream_state os; ogg_stream_state so; /* ogg stream for skeleton bitstream */ ogg_page og; ogg_packet op; int bytes_written=0, ret, result; int id=-1; SpeexHeader header; int nframes=1; spx_int32_t complexity=3; const char* speex_version; char vendor_string[64]; char *comments; int comments_length; int close_in=0, close_out=0; int eos=0; spx_int32_t bitrate=0; double cumul_bits=0, enc_frames=0; char first_bytes[12]; int wave_input=0; spx_int32_t tmp; #ifdef USE_SPEEXDSP SpeexPreprocessState *preprocess = NULL; int denoise_enabled=0, agc_enabled=0; #endif int highpass_enabled=1; int output_rate=0; spx_int32_t lookahead = 0; speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); snprintf(vendor_string, sizeof(vendor_string), "Encoded with Speex %s", speex_version); comment_init(&comments, &comments_length, vendor_string); /*Process command-line options*/ while(1) { c = getopt_long (argc, argv, "nwuhvV", long_options, &option_index); if (c==-1) break; switch(c) { case 0: if (strcmp(long_options[option_index].name,"narrowband")==0) { modeID = SPEEX_MODEID_NB; } else if (strcmp(long_options[option_index].name,"wideband")==0) { modeID = SPEEX_MODEID_WB; } else if (strcmp(long_options[option_index].name,"ultra-wideband")==0) { modeID = SPEEX_MODEID_UWB; } else if (strcmp(long_options[option_index].name,"vbr")==0) { vbr_enabled=1; } else if (strcmp(long_options[option_index].name,"vbr-max-bitrate")==0) { vbr_max=atoi(optarg); if (vbr_max<1) { fprintf (stderr, "Invalid VBR max bit-rate value: %d\n", vbr_max); exit(1); } } else if (strcmp(long_options[option_index].name,"abr")==0) { abr_enabled=atoi(optarg); if (!abr_enabled) { fprintf (stderr, "Invalid ABR value: %d\n", abr_enabled); exit(1); } } else if (strcmp(long_options[option_index].name,"vad")==0) { vad_enabled=1; } else if (strcmp(long_options[option_index].name,"dtx")==0) { dtx_enabled=1; } else if (strcmp(long_options[option_index].name,"quality")==0) { quality = atoi (optarg); vbr_quality=atof(optarg); } else if (strcmp(long_options[option_index].name,"bitrate")==0) { bitrate = atoi (optarg); } else if (strcmp(long_options[option_index].name,"nframes")==0) { nframes = atoi (optarg); if (nframes<1) nframes=1; if (nframes>10) nframes=10; } else if (strcmp(long_options[option_index].name,"comp")==0) { complexity = atoi (optarg); #ifdef USE_SPEEXDSP } else if (strcmp(long_options[option_index].name,"denoise")==0) { denoise_enabled=1; } else if (strcmp(long_options[option_index].name,"agc")==0) { agc_enabled=1; #endif } else if (strcmp(long_options[option_index].name,"no-highpass")==0) { highpass_enabled=0; } else if (strcmp(long_options[option_index].name,"skeleton")==0) { with_skeleton=1; } else if (strcmp(long_options[option_index].name,"help")==0) { usage(); exit(0); } else if (strcmp(long_options[option_index].name,"quiet")==0) { quiet = 1; } else if (strcmp(long_options[option_index].name,"version")==0) { version(); exit(0); } else if (strcmp(long_options[option_index].name,"version-short")==0) { version_short(); exit(0); } else if (strcmp(long_options[option_index].name,"print-rate")==0) { output_rate=1; } else if (strcmp(long_options[option_index].name,"le")==0) { lsb=1; } else if (strcmp(long_options[option_index].name,"be")==0) { lsb=0; } else if (strcmp(long_options[option_index].name,"8bit")==0) { fmt=8; } else if (strcmp(long_options[option_index].name,"16bit")==0) { fmt=16; } else if (strcmp(long_options[option_index].name,"stereo")==0) { chan=2; } else if (strcmp(long_options[option_index].name,"rate")==0) { rate=atoi (optarg); } else if (strcmp(long_options[option_index].name,"comment")==0) { if (!strchr(optarg, '=')) { fprintf (stderr, "Invalid comment: %s\n", optarg); fprintf (stderr, "Comments must be of the form name=value\n"); exit(1); } comment_add(&comments, &comments_length, NULL, optarg); } else if (strcmp(long_options[option_index].name,"author")==0) { comment_add(&comments, &comments_length, "author=", optarg); } else if (strcmp(long_options[option_index].name,"title")==0) { comment_add(&comments, &comments_length, "title=", optarg); } break; case 'n': modeID = SPEEX_MODEID_NB; break; case 'h': usage(); exit(0); break; case 'v': version(); exit(0); break; case 'V': print_bitrate=1; break; case 'w': modeID = SPEEX_MODEID_WB; break; case 'u': modeID = SPEEX_MODEID_UWB; break; case '?': usage(); exit(1); break; } } if (argc-optind!=2) { usage(); exit(1); } inFile=argv[optind]; outFile=argv[optind+1]; /*Initialize Ogg stream struct*/ srand(time(NULL)); if (ogg_stream_init(&os, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } if (with_skeleton && ogg_stream_init(&so, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } 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(inFile, "rb"); if (!fin) { perror(inFile); exit(1); } close_in=1; } { if (fread(first_bytes, 1, 12, fin) != 12) { perror("short file"); exit(1); } if (strncmp(first_bytes,"RIFF",4)==0 || strncmp(first_bytes,"riff",4)==0) { if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1) exit(1); wave_input=1; lsb=1; /* CHECK: exists big-endian .wav ?? */ } } if (modeID==-1 && !rate) { /* By default, use narrowband/8 kHz */ modeID = SPEEX_MODEID_NB; rate=8000; } else if (modeID!=-1 && rate) { mode = speex_lib_get_mode (modeID); if (rate>48000) { fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate); exit(1); } else if (rate>25000) { if (modeID != SPEEX_MODEID_UWB) { fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try ultra-wideband instead\n", mode->modeName , rate); } } else if (rate>12500) { if (modeID != SPEEX_MODEID_WB) { fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try wideband instead\n", mode->modeName , rate); } } else if (rate>=6000) { if (modeID != SPEEX_MODEID_NB) { fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try narrowband instead\n", mode->modeName , rate); } } else { fprintf (stderr, "Error: sampling rate too low: %d Hz\n", rate); exit(1); } } else if (modeID==-1) { if (rate>48000) { fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate); exit(1); } else if (rate>25000) { modeID = SPEEX_MODEID_UWB; } else if (rate>12500) { modeID = SPEEX_MODEID_WB; } else if (rate>=6000) { modeID = SPEEX_MODEID_NB; } else { fprintf (stderr, "Error: Sampling rate too low: %d Hz\n", rate); exit(1); } } else if (!rate) { if (modeID == SPEEX_MODEID_NB) rate=8000; else if (modeID == SPEEX_MODEID_WB) rate=16000; else if (modeID == SPEEX_MODEID_UWB) rate=32000; } if (!quiet) if (rate!=8000 && rate!=16000 && rate!=32000) fprintf (stderr, "Warning: Speex is only optimized for 8, 16 and 32 kHz. It will still work at %d Hz but your mileage may vary\n", rate); if (!mode) mode = speex_lib_get_mode (modeID); speex_init_header(&header, rate, 1, mode); header.frames_per_packet=nframes; header.vbr=vbr_enabled; header.nb_channels = chan; { char *st_string="mono"; if (chan==2) st_string="stereo"; if (!quiet) fprintf (stderr, "Encoding %d Hz audio using %s mode (%s)\n", header.rate, mode->modeName, st_string); } /*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n", header.rate, mode->bitrate, mode->modeName);*/ /*Initialize Speex encoder*/ st = speex_encoder_init(mode); if (strcmp(outFile,"-")==0) { #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif fout=stdout; } else { fout = fopen(outFile, "wb"); if (!fout) { perror(outFile); exit(1); } close_out=1; } speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size); speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity); speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &rate); if (quality >= 0) { if (vbr_enabled) { if (vbr_max>0) speex_encoder_ctl(st, SPEEX_SET_VBR_MAX_BITRATE, &vbr_max); speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_quality); } else speex_encoder_ctl(st, SPEEX_SET_QUALITY, &quality); } if (bitrate) { if (quality >= 0 && vbr_enabled) fprintf (stderr, "Warning: --bitrate option is overriding --quality\n"); speex_encoder_ctl(st, SPEEX_SET_BITRATE, &bitrate); } if (vbr_enabled) { tmp=1; speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); } else if (vad_enabled) { tmp=1; speex_encoder_ctl(st, SPEEX_SET_VAD, &tmp); } if (dtx_enabled) speex_encoder_ctl(st, SPEEX_SET_DTX, &tmp); if (dtx_enabled && !(vbr_enabled || abr_enabled || vad_enabled)) { fprintf (stderr, "Warning: --dtx is useless without --vad, --vbr or --abr\n"); } else if ((vbr_enabled || abr_enabled) && (vad_enabled)) { fprintf (stderr, "Warning: --vad is already implied by --vbr or --abr\n"); } if (with_skeleton) { fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n"); } if (abr_enabled) { speex_encoder_ctl(st, SPEEX_SET_ABR, &abr_enabled); } speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &highpass_enabled); speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); #ifdef USE_SPEEXDSP if (denoise_enabled || agc_enabled) { preprocess = speex_preprocess_state_init(frame_size, rate); speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DENOISE, &denoise_enabled); speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC, &agc_enabled); lookahead += frame_size; } #endif /* first packet should be the skeleton header. */ if (with_skeleton) { add_fishead_packet(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n"); exit(1); } else bytes_written += ret; } /*Write header*/ { int packet_size; op.packet = (unsigned char *)speex_header_to_packet(&header, &packet_size); 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); free(op.packet); while((result = ogg_stream_flush(&os, &og))) { if(!result) break; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } op.packet = (unsigned char *)comments; op.bytes = comments_length; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = 1; ogg_stream_packetin(&os, &op); } /* fisbone packet should be write after all bos pages */ if (with_skeleton) { add_fisbone_packet(&so, os.serialno, &header); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n"); exit(1); } else bytes_written += ret; } /* writing the rest of the speex header packets */ while((result = ogg_stream_flush(&os, &og))) { if(!result) break; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } free(comments); /* write the skeleton eos packet */ if (with_skeleton) { add_eos_packet_to_stream(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton header to output stream\n"); exit(1); } else bytes_written += ret; } speex_bits_init(&bits); if (!wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } if (nb_samples==0) eos=1; total_samples += nb_samples; nb_encoded = -lookahead; /*Main encoding loop (one frame per iteration)*/ while (!eos || total_samples>nb_encoded) { id++; /*Encode current frame*/ if (chan==2) speex_encode_stereo_int(input, frame_size, &bits); #ifdef USE_SPEEXDSP if (preprocess) speex_preprocess(preprocess, input, NULL); #endif speex_encode_int(st, input, &bits); nb_encoded += frame_size; if (print_bitrate) { int tmp; char ch=13; speex_encoder_ctl(st, SPEEX_GET_BITRATE, &tmp); fputc (ch, stderr); cumul_bits += tmp; enc_frames += 1; if (!quiet) { if (vad_enabled || vbr_enabled || abr_enabled) fprintf (stderr, "Bitrate is use: %d bps (average %d bps) ", tmp, (int)(cumul_bits/enc_frames)); else fprintf (stderr, "Bitrate is use: %d bps ", tmp); if (output_rate) printf ("%d\n", tmp); } } if (wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL); } if (nb_samples==0) { eos=1; } if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; total_samples += nb_samples; if ((id+1)%nframes!=0) continue; speex_bits_insert_terminator(&bits); nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); speex_bits_reset(&bits); op.packet = (unsigned char *)cbits; op.bytes = nbBytes; op.b_o_s = 0; /*Is this redundent?*/ if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; op.granulepos = (id+1)*frame_size-lookahead; if (op.granulepos>total_samples) op.granulepos = total_samples; /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/ op.packetno = 2+id/nframes; ogg_stream_packetin(&os, &op); /*Write all new pages (most likely 0 or 1)*/ while (ogg_stream_pageout(&os,&og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } } if ((id+1)%nframes!=0) { while ((id+1)%nframes!=0) { id++; speex_bits_pack(&bits, 15, 5); } nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); op.packet = (unsigned char *)cbits; op.bytes = nbBytes; op.b_o_s = 0; op.e_o_s = 1; op.granulepos = (id+1)*frame_size-lookahead; if (op.granulepos>total_samples) op.granulepos = total_samples; op.packetno = 2+id/nframes; ogg_stream_packetin(&os, &op); } /*Flush all pages left to be written*/ while (ogg_stream_flush(&os, &og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } speex_encoder_destroy(st); speex_bits_destroy(&bits); ogg_stream_clear(&os); if (close_in) fclose(fin); if (close_out) fclose(fout); return 0; }
int convert( const char* source_path, const char* target_path, int bitRate, int quality) { static const input_format raw_format = {NULL, 0, raw_open, wav_close, "raw",N_("RAW file reader")}; int i, ret; int cline_size; OpusMSEncoder *st; const char *opus_version; unsigned char *packet; #ifdef FIXED_POINT opus_int16 *input; #else float *input; #endif /*I/O*/ oe_enc_opt inopt; const input_format *in_format; 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=bitRate * 1000; 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 - quality; // 10 -- best 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; 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; start_time = time(NULL); srand(((getpid()&65535)<<15)^start_time); serialno=rand(); opus_version= "libopus 1.1.1"; //opus_get_version_string(); // Vendor string should just be the encoder library, the ENCODER comment specifies the tool used. if( comment_init(&inopt.comments, &inopt.comments_length, opus_version) ) { return 1; // failed } snprintf(ENCODER_string, sizeof(ENCODER_string), "%s %s",PACKAGE_NAME,PACKAGE_VERSION); if( comment_add(&inopt.comments, &inopt.comments_length, "ENCODER", ENCODER_string) ) { return 1; // failed } if(cline_size>0){ if( comment_add(&inopt.comments, &inopt.comments_length, "ENCODER_OPTIONS", ENCODER_string) ) { return 1; // failed } } fin=fopen_utf8(source_path, "rb"); if(!fin){ perror(source_path); return 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){ LOGD("Error parsing input file: %s\n",source_path); return 1; } if(downmix==0&&inopt.channels>2&&bitrate>0&&bitrate<(16000*inopt.channels)){ if(!quiet)LOGD("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){ LOGD("Notice: Using resampling with complexity<10.\n"); LOGD("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 st=opus_multistream_surround_encoder_create(coding_rate, chan, header.channel_mapping, &header.nb_streams, &header.nb_coupled, header.stream_map, OPUS_APPLICATION_AUDIO, &ret); if(ret!=OPUS_OK){ LOGD( "Error cannot create encoder: %s\n", opus_strerror(ret)); return 1; } min_bytes=max_frame_bytes=(1275*3+7)*header.nb_streams; packet=malloc(sizeof(unsigned char)*max_frame_bytes); if(packet==NULL){ LOGD("Error allocating packet buffer.\n"); return 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 int phase2_getc () { int c; int lineno; c = phase1_getc (); if (c == '-') { c = phase1_getc (); if (c == '-') { /* It starts with '--', so it must be either a short or a long comment. */ c = phase1_getc (); if (c == '[') { c = phase1_getc (); int esigns = 0; while (c == '=') { esigns++; c = phase1_getc (); } if (c == '[') { /* Long comment. */ bool right_bracket = false; bool end = false; int esigns2 = 0; lineno = line_number; comment_start (); while (!end) { c = phase1_getc (); if (c == EOF) break; /* Ignore leading spaces and tabs. */ if (buflen == 0 && (c == ' ' || c == '\t')) continue; comment_add (c); switch (c) { case ']': if (!right_bracket) { right_bracket = true; esigns2 = 0; } else { if (esigns2 == esigns) { comment_line_end (2 + esigns); end = true; } } break; case '=': if (right_bracket) esigns2++; break; case '\n': comment_line_end (1); comment_start (); lineno = line_number; /* Intentionally not breaking. */ default: right_bracket = false; } } last_comment_line = lineno; return ' '; } else { /* One line (short) comment, starting with '--[=...='. */ lineno = last_comment_line; comment_start (); comment_add ('['); while (esigns--) comment_add ('='); phase1_ungetc (c); eat_comment_line (); last_comment_line = lineno; return '\n'; } } else { /* One line (short) comment. */ lineno = line_number; comment_start (); phase1_ungetc (c); eat_comment_line (); last_comment_line = lineno; return '\n'; } } else { /* Minus sign. */ phase1_ungetc (c); return '-'; } } else return c; }
int SpeexEncoder::Initialize(const char* filename, char* modeInput, int channels, int pcmRate) { char *comments; int comments_length; fprintf(stderr, "SpeexEncoder: Initialize\n"); SpeexHeader header; fprintf(stderr, "modeInput: %s\n", modeInput); if (modeInput != NULL){ if (strcmp(modeInput, "narrowband") == 0) { modeID = SPEEX_MODEID_NB; } else if (strcmp(modeInput, "wideband") == 0) { modeID = SPEEX_MODEID_WB; } else if (strcmp(modeInput, "ultra-wideband") == 0) { modeID = SPEEX_MODEID_UWB; } } if (channels > 0){ chan = channels; } speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); snprintf(vendor_string, sizeof(vendor_string), "Encoded with Speex %s", speex_version); comment_init(&comments, &comments_length, vendor_string); comment_add(&comments, &comments_length, "TITLE=", "saa1"); comment_add(&comments, &comments_length, "AUTHOR=", "uptivity"); comment_add(&comments, &comments_length, "FORMATTYPE=", (char*)speex_version); comment_add(&comments, &comments_length, "DURATION=", "00000"); /*Initialize Ogg stream struct*/ srand(time(NULL)); if (ogg_stream_init(&os, rand()) == -1) { fprintf(stderr, "Error: stream init failed\n"); exit(1); } rate = pcmRate; if (modeID == -1 ) { /* By default, use narrowband/8 kHz */ modeID = SPEEX_MODEID_NB; if (pcmRate < 0){ rate = 8000; } } if (pcmRate < 0){ if (modeID == SPEEX_MODEID_NB) rate = 8000; else if (modeID == SPEEX_MODEID_WB) rate = 16000; else if (modeID == SPEEX_MODEID_UWB) rate = 32000; } if (!mode) mode = speex_lib_get_mode(modeID); speex_init_header(&header, rate, 1, mode); header.frames_per_packet = 1; header.vbr = 0; header.nb_channels = chan; { char *st_string = "mono"; if (chan == 2) st_string = "stereo"; fprintf(stderr, "Encoding %d Hz audio using %s mode (%s)\n", header.rate, mode->modeName, st_string); } /*Initialize Speex encoder*/ st = speex_encoder_init(mode); fout = fopen(filename, "wb"); if (!fout) { perror(filename); exit(1); } speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size); speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity); speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &rate); if (quality >= 0) { speex_encoder_ctl(st, SPEEX_SET_QUALITY, &quality); } speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); /*Write header*/ { int packet_size; op.packet = (unsigned char *)speex_header_to_packet(&header, &packet_size); op.bytes = packet_size; op.b_o_s = 1; op.e_o_s = 0; op.granulepos = 0; op.packetno = 0; // submit the packet to the ogg streaming layer ogg_stream_packetin(&os, &op); free(op.packet); while ((result = ogg_stream_flush(&os, &og))) { if (!result) break; ret = oe_write_page(&og, fout); if (ret != og.header_len + og.body_len) { fprintf(stderr, "Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } op.packet = (unsigned char *)comments; op.bytes = comments_length; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = 1; ogg_stream_packetin(&os, &op); durationIndex = bytes_written + os.header_fill + os.body_fill - 5; } /* writing the rest of the speex header packets */ while ((result = ogg_stream_flush(&os, &og))) { if (!result) break; ret = oe_write_page(&og, fout); if (ret != og.header_len + og.body_len) { fprintf(stderr, "Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } free(comments); speex_bits_init(&bits); return 0; }