/* set up the encoder state */ static gboolean gst_two_lame_setup (GstTwoLame * twolame) { #define CHECK_ERROR(command) G_STMT_START {\ if ((command) < 0) { \ GST_ERROR_OBJECT (twolame, "setup failed: " G_STRINGIFY (command)); \ return FALSE; \ } \ }G_STMT_END int retval; GstCaps *allowed_caps; GST_DEBUG_OBJECT (twolame, "starting setup"); /* check if we're already setup; if we are, we might want to check * if this initialization is compatible with the previous one */ /* FIXME: do this */ if (twolame->setup) { GST_WARNING_OBJECT (twolame, "already setup"); twolame->setup = FALSE; } twolame->glopts = twolame_init (); if (twolame->glopts == NULL) return FALSE; /* copy the parameters over */ twolame_set_in_samplerate (twolame->glopts, twolame->samplerate); /* let twolame choose default samplerate unless outgoing sample rate is fixed */ allowed_caps = gst_pad_get_allowed_caps (twolame->srcpad); if (allowed_caps != NULL) { GstStructure *structure; gint samplerate; structure = gst_caps_get_structure (allowed_caps, 0); if (gst_structure_get_int (structure, "rate", &samplerate)) { GST_DEBUG_OBJECT (twolame, "Setting sample rate to %d as fixed in src caps", samplerate); twolame_set_out_samplerate (twolame->glopts, samplerate); } else { GST_DEBUG_OBJECT (twolame, "Letting twolame choose sample rate"); twolame_set_out_samplerate (twolame->glopts, 0); } gst_caps_unref (allowed_caps); allowed_caps = NULL; } else { GST_DEBUG_OBJECT (twolame, "No peer yet, letting twolame choose sample rate"); twolame_set_out_samplerate (twolame->glopts, 0); } /* force mono encoding if we only have one channel */ if (twolame->num_channels == 1) twolame->mode = 3; /* Fix bitrates and MPEG version */ CHECK_ERROR (twolame_set_num_channels (twolame->glopts, twolame->num_channels)); CHECK_ERROR (twolame_set_mode (twolame->glopts, twolame->mode)); CHECK_ERROR (twolame_set_psymodel (twolame->glopts, twolame->psymodel)); CHECK_AND_FIXUP_BITRATE (twolame, "bitrate", twolame->bitrate); CHECK_ERROR (twolame_set_bitrate (twolame->glopts, twolame->bitrate)); CHECK_ERROR (twolame_set_padding (twolame->glopts, twolame->padding)); CHECK_ERROR (twolame_set_energy_levels (twolame->glopts, twolame->energy_level_extension)); CHECK_ERROR (twolame_set_emphasis (twolame->glopts, twolame->emphasis)); CHECK_ERROR (twolame_set_error_protection (twolame->glopts, twolame->error_protection)); CHECK_ERROR (twolame_set_copyright (twolame->glopts, twolame->copyright)); CHECK_ERROR (twolame_set_original (twolame->glopts, twolame->original)); CHECK_ERROR (twolame_set_VBR (twolame->glopts, twolame->vbr)); CHECK_ERROR (twolame_set_VBR_level (twolame->glopts, twolame->vbr_level)); CHECK_ERROR (twolame_set_ATH_level (twolame->glopts, twolame->ath_level)); CHECK_AND_FIXUP_BITRATE (twolame, "vbr-max-bitrate", twolame->vbr_max_bitrate); CHECK_ERROR (twolame_set_VBR_max_bitrate_kbps (twolame->glopts, twolame->vbr_max_bitrate)); CHECK_ERROR (twolame_set_quick_mode (twolame->glopts, twolame->quick_mode)); CHECK_ERROR (twolame_set_quick_count (twolame->glopts, twolame->quick_mode_count)); /* initialize the twolame encoder */ if ((retval = twolame_init_params (twolame->glopts)) >= 0) { twolame->setup = TRUE; /* FIXME: it would be nice to print out the mode here */ GST_INFO ("twolame encoder setup (%d kbit/s, %d Hz, %d channels)", twolame->bitrate, twolame->samplerate, twolame->num_channels); } else { GST_ERROR_OBJECT (twolame, "twolame_init_params returned %d", retval); } GST_DEBUG_OBJECT (twolame, "done with setup"); return twolame->setup; #undef CHECK_ERROR }
int mpae_init_twolame(audio_encoder_t *encoder) { int mode; mpae_twolame_ctx *ctx = NULL; if(encoder->params.channels == 1) { mp_msg(MSGT_MENCODER, MSGL_INFO, "ae_twolame, 1 audio channel, forcing mono mode\n"); mode = TWOLAME_MONO; } else if(encoder->params.channels == 2) { if(! strcasecmp(param_mode, "dual")) mode = TWOLAME_DUAL_CHANNEL; else if(! strcasecmp(param_mode, "jstereo")) mode = TWOLAME_JOINT_STEREO; else if(! strcasecmp(param_mode, "stereo")) mode = TWOLAME_STEREO; else { mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, unknown mode %s, exiting\n", param_mode); } } else mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, Twolame can't encode > 2 channels, exiting\n"); ctx = (mpae_twolame_ctx *) calloc(1, sizeof(mpae_twolame_ctx)); if(ctx == NULL) { mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, couldn't alloc a %d bytes context, exiting\n", sizeof(mpae_twolame_ctx)); return 0; } ctx->twolame_ctx = twolame_init(); if(ctx->twolame_ctx == NULL) { mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, couldn't initial parameters from libtwolame, exiting\n"); free(ctx); return 0; } ctx->vbr = 0; if(twolame_set_num_channels(ctx->twolame_ctx, encoder->params.channels) != 0) return 0; if(twolame_set_mode(ctx->twolame_ctx, mode) != 0) return 0; if(twolame_set_in_samplerate(ctx->twolame_ctx, encoder->params.sample_rate) != 0) return 0; if(twolame_set_out_samplerate(ctx->twolame_ctx, encoder->params.sample_rate) != 0) return 0; if(encoder->params.sample_rate < 32000) twolame_set_version(ctx->twolame_ctx, TWOLAME_MPEG2); else twolame_set_version(ctx->twolame_ctx, TWOLAME_MPEG1); if(twolame_set_psymodel(ctx->twolame_ctx, param_psy) != 0) return 0; if(twolame_set_bitrate(ctx->twolame_ctx, param_bitrate) != 0) return 0; if(param_errprot) if(twolame_set_error_protection(ctx->twolame_ctx, TRUE) != 0) return 0; if(param_vbr != 0) { if(twolame_set_VBR(ctx->twolame_ctx, TRUE) != 0) return 0; if(twolame_set_VBR_q(ctx->twolame_ctx, param_vbr) != 0) return 0; if(twolame_set_padding(ctx->twolame_ctx, FALSE) != 0) return 0; if(param_maxvbr) { if(twolame_set_VBR_max_bitrate_kbps(ctx->twolame_ctx, param_maxvbr) != 0) return 0; } ctx->vbr = 1; } if(twolame_set_verbosity(ctx->twolame_ctx, param_debug) != 0) return 0; if(twolame_init_params(ctx->twolame_ctx) != 0) return 0; encoder->params.bitrate = param_bitrate * 1000; encoder->params.samples_per_frame = 1152; encoder->priv = ctx; encoder->decode_buffer_size = 1152 * 2 * encoder->params.channels; encoder->bind = bind_twolame; encoder->get_frame_size = get_frame_size; encoder->encode = encode_twolame; encoder->close = close_twolame; return 1; }
/* parse_args() Parse the command line arguments */ void parse_args(int argc, char **argv, twolame_options * encopts ) { int ch=0; // process args struct option longopts[] = { // Input { "raw-input", no_argument, NULL, 'r' }, { "byte-swap", no_argument, NULL, 'x' }, { "samplerate", required_argument, NULL, 's' }, { "channels", required_argument, NULL, 'N' }, { "swap-channels", no_argument, NULL, 'g' }, { "scale", required_argument, NULL, 1000 }, { "scale-l", required_argument, NULL, 1001 }, { "scale-r", required_argument, NULL, 1002 }, // Output { "mode", required_argument, NULL, 'm' }, { "downmix", no_argument, NULL, 'a' }, { "bitrate", required_argument, NULL, 'b' }, { "psyc-mode", required_argument, NULL, 'P' }, { "vbr", no_argument, NULL, 'v' }, { "vbr-level", required_argument, NULL, 'V' }, { "max-bitrate", required_argument, NULL, 'B' }, { "ath", required_argument, NULL, 'l' }, { "quick", required_argument, NULL, 'q' }, { "single-frame", no_argument, NULL, 'S' }, // Misc { "copyright", no_argument, NULL, 'c' }, { "non-original", no_argument, NULL, 'o' }, { "original", no_argument, NULL, 1003 }, { "protect", no_argument, NULL, 'p' }, { "padding", no_argument, NULL, 'd' }, { "reserve-bits", required_argument, NULL, 'R' }, { "deemphasis", required_argument, NULL, 'e' }, { "energy", no_argument, NULL, 'E' }, // Verbosity { "talkativity", required_argument, NULL, 't' }, { "quiet", no_argument, NULL, 1004 }, { "brief", no_argument, NULL, 1005 }, { "verbose", no_argument, NULL, 1006 }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; // Create a short options structure from the long one char* shortopts = build_shortopt_string( longopts ); //printf("shortopts: %s\n", shortopts); while( (ch = getopt_long( argc, argv, shortopts, longopts, NULL )) != -1) { switch(ch) { // Input case 'r': sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16; break; case 'x': byteswap = TRUE; break; case 's': twolame_set_out_samplerate(encopts, atoi(optarg)); sfinfo.samplerate = atoi(optarg); break; case 'N': sfinfo.channels = atoi(optarg); break; case 'g': channelswap = TRUE; break; case 1000: // --scale twolame_set_scale( encopts, atof(optarg) ); break; case 1001: // --scale-l twolame_set_scale_left( encopts, atof(optarg) ); break; case 1002: // --scale-r twolame_set_scale_right( encopts, atof(optarg) ); break; // Output case 'm': if (*optarg == 's') { twolame_set_mode(encopts, TWOLAME_STEREO); } else if (*optarg == 'd') { twolame_set_mode(encopts, TWOLAME_DUAL_CHANNEL); } else if (*optarg == 'j') { twolame_set_mode(encopts, TWOLAME_JOINT_STEREO); } else if (*optarg == 'm') { twolame_set_mode(encopts, TWOLAME_MONO); } else if (*optarg == 'a') { twolame_set_mode(encopts, TWOLAME_AUTO_MODE); } else { fprintf(stderr, "Error: mode must be a/s/d/j/m not '%s'\n\n", optarg); usage_long(); } break; case 'a': // downmix twolame_set_mode(encopts, TWOLAME_MONO); break; case 'b': twolame_set_bitrate(encopts, atoi(optarg)); break; case 'P': twolame_set_psymodel(encopts, atoi(optarg)); break; case 'v': twolame_set_VBR(encopts, TRUE); break; case 'V': twolame_set_VBR(encopts, TRUE); twolame_set_VBR_level(encopts, atof(optarg)); break; case 'B': twolame_set_VBR_max_bitrate_kbps(encopts, atoi(optarg)); break; case 'l': twolame_set_ATH_level(encopts, atof(optarg)); break; case 'q': twolame_set_quick_mode(encopts, TRUE); twolame_set_quick_count(encopts, atoi(optarg)); break; case 'S': single_frame_mode = TRUE; break; // Miscellaneous case 'c': twolame_set_copyright(encopts, TRUE); break; case 'o': // --non-original twolame_set_original(encopts, FALSE); break; case 1003: // --original twolame_set_original(encopts, TRUE); break; case 'p': twolame_set_error_protection(encopts, TRUE); break; case 'd': twolame_set_padding(encopts, TWOLAME_PAD_ALL); break; case 'R': twolame_set_num_ancillary_bits(encopts, atoi(optarg)); break; case 'e': if (*optarg == 'n') twolame_set_emphasis(encopts, TWOLAME_EMPHASIS_N); else if (*optarg == '5') twolame_set_emphasis(encopts, TWOLAME_EMPHASIS_5); else if (*optarg == 'c') twolame_set_emphasis(encopts, TWOLAME_EMPHASIS_C); else { fprintf(stderr, "Error: emphasis must be n/5/c not '%s'\n\n", optarg); usage_long(); } break; case 'E': twolame_set_energy_levels(encopts, TRUE); break; // Verbosity case 't': twolame_set_verbosity(encopts, atoi(optarg)); break; case 1004: // --quiet twolame_set_verbosity(encopts, 0); break; case 1005: // --brief twolame_set_verbosity(encopts, 1); break; case 1006: // --verbose twolame_set_verbosity(encopts, 4); break; case 'h': usage_long(); break; default: usage_short(); break; } } // Look for the input and output file names argc -= optind; argv += optind; while( argc ) { if (inputfilename[0] == '\0') strncpy(inputfilename, *argv, MAX_NAME_SIZE); else if (outputfilename[0] == '\0') strncpy(outputfilename, *argv, MAX_NAME_SIZE); else { fprintf(stderr, "excess argument: %s\n", *argv); usage_short(); } argv++; argc--; } // Check that we now have input and output file names ok if ( inputfilename[0] == '\0') { fprintf(stderr, "Missing input filename.\n"); usage_short(); } if ( outputfilename[0] == '\0' && strcmp(inputfilename, "-")!=0 ) { // Create output filename from the inputfilename // and change the suffix new_extension( inputfilename, OUTPUT_SUFFIX, outputfilename ); } if ( outputfilename[0] == '\0') { fprintf(stderr, "Missing output filename.\n"); usage_short(); } }
int twolame_init_params (twolame_options *glopts) { if (glopts->twolame_init) { fprintf(stderr,"Already called twolame_init_params() once.\n"); return 1; } // Check the number of channels if (glopts->num_channels != 1 && glopts->num_channels != 2) { fprintf(stderr,"twolame_init_params(): must specify number of channels in input samples using twolame_set_num_channels().\n"); return -1; } // If not output samplerate has been set, then set it to the input sample rate if (glopts->samplerate_out < 1) { glopts->samplerate_out = glopts->samplerate_in; } // If the MPEG version has not been set, then choose automatically if (glopts->version == -1) { // Get the MPEG version for the chosen samplerate glopts->version = twolame_get_version_for_samplerate( glopts->samplerate_out ); if (glopts->version < 0) { fprintf(stdout,"twolame_init_params(): invalid samplerate: %i\n", glopts->samplerate_out ); return -1; } else if (glopts->verbosity>=3) { fprintf(stderr, "Chosen version '%s' for samplerate of %d Hz.\n", twolame_mpeg_version_name(glopts->version), glopts->samplerate_out); } } // Choose mode (if none chosen) if (glopts->mode == TWOLAME_AUTO_MODE) { if (glopts->num_channels == 2) glopts->mode = TWOLAME_STEREO; else glopts->mode = TWOLAME_MONO; if (glopts->verbosity>=3) { fprintf(stderr, "Chosen mode to be '%s' because of %d input channels.\n", twolame_get_mode_name(glopts), glopts->num_channels); } } // Choose the bitrate (if none chosen) if (glopts->bitrate <= 0) { if (glopts->mode == TWOLAME_MONO) { switch(glopts->samplerate_out) { case 48000: glopts->bitrate = 96; break; // (LAME=64) case 44100: glopts->bitrate = 96; break; // (LAME=64) case 32000: glopts->bitrate = 80; break; // (LAME=48) case 24000: glopts->bitrate = 48; break; // (LAME=32) case 22050: glopts->bitrate = 48; break; // (LAME=32) case 16000: glopts->bitrate = 32; break; // (LAME=24) } } else { switch(glopts->samplerate_out) { case 48000: glopts->bitrate = 192; break; // (LAME=128) case 44100: glopts->bitrate = 192; break; // (LAME=128) case 32000: glopts->bitrate = 160; break; // (LAME=96) case 24000: glopts->bitrate = 96; break; // (LAME=64) case 22050: glopts->bitrate = 96; break; // (LAME=64) case 16000: glopts->bitrate = 64; break; // (LAME=48) } } if (glopts->verbosity>=3) { fprintf(stderr, "Chosen bitrate of %dkbps for samplerate of %d Hz.\n", glopts->bitrate, glopts->samplerate_out); } } /* Can't do DAB and energylevel extensions at the same time Because both of them think they're the only ones inserting information into the ancillary section of the frame */ if (glopts->do_dab && glopts->do_energy_levels) { fprintf(stderr,"Can't do DAB and Energy Levels at the same time\n"); return -1; } /* Check that if we're doing energy levels, that there's enough space to put the information */ if (glopts->do_energy_levels) { if ((glopts->mode==TWOLAME_MONO)&&(glopts->num_ancillary_bits<16)) { fprintf(stderr,"Too few ancillary bits: %i<16\n",glopts->num_ancillary_bits); glopts->num_ancillary_bits = 16; } if ((glopts->mode!=TWOLAME_MONO)&&(glopts->num_ancillary_bits<40)) { fprintf(stderr,"Too few ancillary bits: %i<40\n",glopts->num_ancillary_bits); glopts->num_ancillary_bits = 40; } } /* * MFC Feb 2003: in VBR mode, joint * stereo doesn't make any sense at * the moment, as there are no noisy * subbands according to * bits_for_nonoise in vbr mode */ if (glopts->vbr && glopts->mode==TWOLAME_JOINT_STEREO) { // force stereo mode twolame_set_mode(glopts, TWOLAME_STEREO); } /* don't use padding for VBR */ if (glopts->vbr) { twolame_set_padding(glopts, FALSE); } //MFC FIX: Need to cross validate the number of ancillary_bits // with the energylevel setting. // // energylevel: // MFC FIX: This option must be mutually exclusive with the // reservebits(-R) option *UNLESS * the number // of explicitly reserved bits > 5 bytes. // If energy information is required, see if we're in MONO mode in // which case, we only need 16 bits of ancillary data if (glopts->do_energy_levels) { if (glopts->mode==TWOLAME_MONO) { // only 2 bytes needed for energy level for mono channel twolame_set_num_ancillary_bits(glopts, 16); } else { // 5 bytes for the stereo energy info twolame_set_num_ancillary_bits(glopts, 40); } } // build mpeg header from parameters if (init_header_info( glopts )<0) { return -1; } // load the alloc tables and do some other stuff if (init_frame_info( glopts )<0) { return -1; } // initialise bitrate allocation if (init_bit_allocation( glopts )<0) { return -1; } // Check input samplerate is same as output samplerate if (glopts->samplerate_out != glopts->samplerate_in) { fprintf(stderr,"twolame_init_params(): sorry, twolame doesn't support resampling (yet).\n"); return -1; } // Initialise interal variables glopts->samples_in_buffer = 0; glopts->psycount = 0; glopts->crc = 0; // Allocate memory to larger buffers glopts->subband = (subband_t *) twolame_malloc (sizeof (subband_t), "subband"); glopts->j_sample = (jsb_sample_t *) twolame_malloc (sizeof (jsb_sample_t), "j_sample"); glopts->sb_sample = (sb_sample_t *) twolame_malloc (sizeof (sb_sample_t), "sb_sample"); // clear buffers memset ((char *) glopts->buffer, 0, sizeof(glopts->buffer)); memset ((char *) glopts->bit_alloc, 0, sizeof (glopts->bit_alloc)); memset ((char *) glopts->scfsi, 0, sizeof (glopts->scfsi)); memset ((char *) glopts->scalar, 0, sizeof (glopts->scalar)); memset ((char *) glopts->j_scale, 0, sizeof (glopts->j_scale)); memset ((char *) glopts->smrdef, 0, sizeof (glopts->smrdef)); memset ((char *) glopts->smr, 0, sizeof (glopts->smr)); memset ((char *) glopts->max_sc, 0, sizeof (glopts->max_sc)); // Initialise subband windowfilter if (init_subband(&glopts->smem)<0) { return -1; } // All initalised now :) glopts->twolame_init++; return(0); }