long MP3_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) { mp3_coder_state* coder_state; int ret_code; coder_state = malloc(sizeof(mp3_coder_state)); if (!coder_state) { ERROR("no memory for allocating mp3 coder state\n"); return -1; } DBG("MP3: creating lame %s\n", get_lame_version()); format_description[0].id = 0; coder_state->gfp = lame_init(); if (!coder_state->gfp) { ERROR("initialiting lame\n"); free(coder_state); return -1; } lame_set_errorf(coder_state->gfp, &no_output); lame_set_debugf(coder_state->gfp, &no_output); lame_set_msgf(coder_state->gfp, &no_output); lame_set_num_channels(coder_state->gfp,1); lame_set_in_samplerate(coder_state->gfp,8000); lame_set_brate(coder_state->gfp,16); lame_set_mode(coder_state->gfp,3); // mono lame_set_quality(coder_state->gfp,2); /* 2=high 5 = medium 7=low */ id3tag_init(coder_state->gfp); id3tag_set_title(coder_state->gfp, "mp3 voicemail by iptel.org"); ret_code = lame_init_params(coder_state->gfp); if (ret_code < 0) { ERROR("lame encoder init failed: return code is %d\n", ret_code); free(coder_state); return -1; } #ifdef WITH_MPG123DECODER coder_state->mpg123_h = mpg123_new(NULL, NULL); if (!coder_state->mpg123_h) { ERROR("initializing mpg123 decoder instance\n"); return -1; } /* suppress output */ mpg123_param(coder_state->mpg123_h, MPG123_FLAGS, MPG123_QUIET /* | MPG123_FORCE_MONO */,0); /* mpg123_param(coder_state->mpg123_h, MPG123_VERBOSE, 0, 0); */ #endif return (long)coder_state; }
static switch_status_t shout_file_open(switch_file_handle_t *handle, const char *path) { shout_context_t *context; char *host, *file; char *username, *password, *port; char *err = NULL; const char *mpg123err = NULL; int portno = 0; if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) { return SWITCH_STATUS_MEMERR; } if (!handle->samplerate) { handle->samplerate = 8000; } context->memory_pool = handle->memory_pool; context->samplerate = handle->samplerate; context->handle = handle; switch_thread_rwlock_create(&(context->rwlock), context->memory_pool); switch_thread_rwlock_rdlock(context->rwlock); switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->memory_pool); if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) { if (switch_buffer_create_dynamic(&context->audio_buffer, TC_BUFFER_SIZE, TC_BUFFER_SIZE * 2, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); goto error; } context->mh = our_mpg123_new(NULL, NULL); if (mpg123_format_all(context->mh) != MPG123_OK) { MPGERROR(); } if (mpg123_param(context->mh, MPG123_FORCE_RATE, context->samplerate, 0) != MPG123_OK) { MPGERROR(); } if (handle->handler) { if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_MONO_MIX, 0) != MPG123_OK) { MPGERROR(); } if (mpg123_open_feed(context->mh) != MPG123_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening mpg feed\n"); mpg123err = mpg123_strerror(context->mh); goto error; } context->stream_url = switch_core_sprintf(context->memory_pool, "http://%s", path); context->prebuf = handle->prebuf; launch_read_stream_thread(context); } else { handle->seekable = 1; if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_MONO_MIX, 0) != MPG123_OK) { MPGERROR(); } if (mpg123_open(context->mh, path) != MPG123_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path); mpg123err = mpg123_strerror(context->mh); goto error; } } } else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Appending to MP3 not supported.\n"); } if (!(context->gfp = lame_init())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n"); goto error; } if (!handle->handler) { id3tag_init(context->gfp); id3tag_v2_only(context->gfp); id3tag_pad_v2(context->gfp); } context->channels = handle->channels; lame_set_brate(context->gfp, 16 * (handle->samplerate / 8000) * handle->channels); lame_set_num_channels(context->gfp, handle->channels); lame_set_in_samplerate(context->gfp, handle->samplerate); lame_set_out_samplerate(context->gfp, handle->samplerate); if (handle->channels == 2) { lame_set_mode(context->gfp, STEREO); } else { lame_set_mode(context->gfp, MONO); } lame_set_quality(context->gfp, 2); /* 2=high 5 = medium 7=low */ lame_set_errorf(context->gfp, log_error); lame_set_debugf(context->gfp, log_debug); lame_set_msgf(context->gfp, log_msg); if (handle->handler) { if (switch_buffer_create_dynamic(&context->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); goto error; } lame_set_bWriteVbrTag(context->gfp, 0); lame_mp3_tags_fid(context->gfp, NULL); username = switch_core_strdup(handle->memory_pool, path); if (!(password = strchr(username, ':'))) { err = "invalid url"; goto error; } *password++ = '\0'; if (!(host = strchr(password, '@'))) { err = "invalid url"; goto error; } *host++ = '\0'; if ((file = strchr(host, '/'))) { *file++ = '\0'; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL: %s\n", path); goto error; } if ((port = strchr(host, ':'))) { *port++ = '\0'; if (port) { portno = atoi(port); } } if (!portno) { portno = 8000; } if (!(context->shout = shout_new())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate shout_t\n"); goto error; } if (shout_set_host(context->shout, host) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting hostname: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_protocol(context->shout, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting protocol: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_port(context->shout, portno) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting port: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_password(context->shout, password) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting password: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_mount(context->shout, file) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting mount: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_user(context->shout, username) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting user: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_url(context->shout, "http://www.freeswitch.org") != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_description(context->shout, "FreeSWITCH mod_shout Broadcasting Module") != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting description: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_audio_info(context->shout, "bitrate", "24000") != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting bitrate: %s\n", shout_get_error(context->shout)); goto error; } if (shout_set_format(context->shout, SHOUT_FORMAT_MP3) != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting format: %s\n", shout_get_error(context->shout)); goto error; } } else { /* lame being lame and all has FILE * coded into it's API for some functions so we gotta use it */ if (!(context->fp = fopen(path, "wb+"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path); goto error; } } } handle->samples = 0; handle->format = 0; handle->sections = 0; handle->speed = 0; handle->private_info = context; switch_thread_rwlock_unlock(context->rwlock); return SWITCH_STATUS_SUCCESS; error: switch_thread_rwlock_unlock(context->rwlock); if (err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: %s\n", err); } if (mpg123err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error from mpg123: %s\n", mpg123err); } free_context(context); return SWITCH_STATUS_GENERR; }
void do_broadcast(switch_stream_handle_t *stream) { char *path_info = switch_event_get_header(stream->param_event, "http-path-info"); char *file; lame_global_flags *gfp = NULL; switch_file_handle_t fh = { 0 }; unsigned char mp3buf[TC_BUFFER_SIZE] = ""; uint8_t buf[1024]; int rlen; int is_local = 0; uint32_t interval = 20000; if (strstr(path_info + 7, "://")) { file = strdup(path_info + 7); is_local++; } else { file = switch_mprintf("%s/streamfiles/%s", SWITCH_GLOBAL_dirs.base_dir, path_info + 7); } assert(file); if (switch_core_file_open(&fh, file, 0, 0, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { memset(&fh, 0, sizeof(fh)); stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File not found</h2>\n"); goto end; } if (switch_test_flag((&fh), SWITCH_FILE_NATIVE)) { stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File format not supported</h2>\n"); goto end; } if (!(gfp = lame_init())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n"); goto end; } lame_set_num_channels(gfp, fh.channels); lame_set_in_samplerate(gfp, fh.samplerate); lame_set_brate(gfp, 16 * (fh.samplerate / 8000) * fh.channels); lame_set_mode(gfp, 3); lame_set_quality(gfp, 2); lame_set_errorf(gfp, log_error); lame_set_debugf(gfp, log_debug); lame_set_msgf(gfp, log_msg); lame_set_bWriteVbrTag(gfp, 0); lame_mp3_tags_fid(gfp, NULL); lame_init_params(gfp); lame_print_config(gfp); stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s.mp3\"\r\n\r\n", path_info + 7); if (fh.interval) { interval = fh.interval * 1000; } for (;;) { switch_size_t samples = sizeof(buf) / 2; switch_core_file_read(&fh, buf, &samples); if (is_local) { switch_yield(interval); } if (!samples) { break; } if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, samples, mp3buf, sizeof(mp3buf))) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); goto end; } if (rlen) { if (stream->raw_write_function(stream, mp3buf, rlen)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n"); goto end; } } } while ((rlen = lame_encode_flush(gfp, mp3buf, sizeof(mp3buf))) > 0) { if (stream->raw_write_function(stream, mp3buf, rlen)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n"); goto end; } } end: if (fh.channels) { switch_core_file_close(&fh); } switch_safe_free(file); if (gfp) { lame_close(gfp); gfp = NULL; } }
void do_telecast(switch_stream_handle_t *stream) { char *path_info = switch_event_get_header(stream->param_event, "http-path-info"); char *uuid = strdup(path_info + 4); switch_core_session_t *tsession; char *fname = "stream.mp3"; if ((fname = strchr(uuid, '/'))) { *fname++ = '\0'; } if (!(tsession = switch_core_session_locate(uuid))) { char *ref = switch_event_get_header(stream->param_event, "http-referer"); stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>Not Found!</h2>\n" "<META http-equiv=\"refresh\" content=\"1;URL=%s\">", ref); } else { switch_media_bug_t *bug = NULL; switch_buffer_t *buffer = NULL; switch_mutex_t *mutex; switch_channel_t *channel = switch_core_session_get_channel(tsession); lame_global_flags *gfp = NULL; switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(tsession, &read_impl); if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stepping into media path so this will work!\n"); switch_ivr_media(uuid, SMF_REBRIDGE); } if (!(gfp = lame_init())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n"); goto end; } lame_set_num_channels(gfp, read_impl.number_of_channels); lame_set_in_samplerate(gfp, read_impl.actual_samples_per_second); lame_set_brate(gfp, 16 * (read_impl.actual_samples_per_second / 8000) * read_impl.number_of_channels); lame_set_mode(gfp, 3); lame_set_quality(gfp, 2); lame_set_errorf(gfp, log_error); lame_set_debugf(gfp, log_debug); lame_set_msgf(gfp, log_msg); lame_set_bWriteVbrTag(gfp, 0); lame_mp3_tags_fid(gfp, NULL); lame_init_params(gfp); lame_print_config(gfp); switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); switch_buffer_create_dynamic(&buffer, 1024, 2048, 0); switch_buffer_add_mutex(buffer, mutex); if (switch_core_media_bug_add(tsession, "telecast", NULL, telecast_callback, buffer, 0, SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING, &bug) != SWITCH_STATUS_SUCCESS) { goto end; } stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s\"\r\n\r\n", fname); while (switch_channel_ready(channel)) { unsigned char mp3buf[TC_BUFFER_SIZE] = ""; int rlen; uint8_t buf[1024]; switch_size_t bytes = 0; if (switch_buffer_inuse(buffer) >= 1024) { switch_buffer_lock(buffer); bytes = switch_buffer_read(buffer, buf, sizeof(buf)); switch_buffer_unlock(buffer); } else { if (!bytes) { switch_cond_next(); continue; } memset(buf, 0, bytes); } if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, bytes / 2, mp3buf, sizeof(mp3buf))) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); goto end; } if (rlen) { if (stream->raw_write_function(stream, mp3buf, rlen)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n"); goto end; } } } end: switch_safe_free(uuid); if (gfp) { lame_close(gfp); gfp = NULL; } if (bug) { switch_core_media_bug_remove(tsession, &bug); } if (buffer) { switch_buffer_destroy(&buffer); } switch_core_session_rwunlock(tsession); } }
int mp3_encode(int fd_in, int fd_out) { lame_global_flags *gfp; uint32_t i, j, k, count; int16_t *b0 = 0, *b1 = 0; unsigned char *c; int ret; /* calculate data size*/ k = (uint32_t) lseek(fd_in, 0, SEEK_CUR); i = (uint32_t) lseek(fd_in, 0, SEEK_END); lseek(fd_in, k, SEEK_SET); i -= k; k = 0; gfp = lame_init(); lame_set_errorf(gfp,lame_error_handler); lame_set_debugf(gfp,lame_error_handler); lame_set_msgf(gfp,lame_error_handler); lame_set_num_channels(gfp,2); lame_set_in_samplerate(gfp,8000); #if 0 lame_set_brate(gfp,64); /* compress 1:4 */ lame_set_mode(gfp,0); /* mode = stereo */ lame_set_quality(gfp,2); /* 2=high 5 = medium 7=low */ #else lame_set_quality(gfp,5); /* 2=high 5 = medium 7=low */ lame_set_mode(gfp,3); /* mode = mono */ if(lame_get_VBR(gfp) == vbr_off) lame_set_VBR(gfp, vbr_default); lame_set_VBR_quality(gfp, 7.0); lame_set_findReplayGain(gfp, 0); lame_set_bWriteVbrTag(gfp, 1); lame_set_out_samplerate(gfp,11025); /* lame_set_num_samples(gfp,i/2); */ #endif if(lame_init_params(gfp) < 0) { log_err("encode: failed to init lame"); return 0; } #define CHSZ (512*1024) #define OCHSZ (5*(CHSZ/8)+7200) b0 = (int16_t *) malloc(OCHSZ); b1 = (int16_t *) malloc(CHSZ); if(!b0 || !b1) { log_err("encode: out of memory"); if(b0) free(b0); if(b1) free(b1); return 0; } do { ret = 0; j = 0; count = 0; for(c = (unsigned char*) b1; count < CHSZ; c += ret) { j = (k + RSZ > i) ? i - k : RSZ; ret = read(fd_in,c,j); if(ret < 0) break; k += ret; count += ret; if(k == i) break; } if(ret < 0) break; if(count) { ret = lame_encode_buffer(gfp,b1,b1,count/2,(unsigned char *)b0,OCHSZ); if(ret < 0) break; c = (unsigned char *) b0; count = ret; for(j = 0; j < count; j += RSZ, c += ret) { ret = (j + RSZ > count) ? count - j : RSZ; write(fd_out,c,ret); } } } while(k < i); k = (uint32_t) lame_encode_flush(gfp,(unsigned char *)b0,OCHSZ); if(k) write(fd_out,b0,k); k = lame_get_lametag_frame(gfp,(unsigned char *)b0,OCHSZ); if(k > 0) write(fd_out,b0,k); lame_close(gfp); free(b0); free(b1); return 1; }
int lame_main(lame_t gf, int argc, char **argv) { char inPath[PATH_MAX + 1]; char outPath[PATH_MAX + 1]; char nogapdir[PATH_MAX + 1]; /* support for "nogap" encoding of up to 200 .wav files */ #define MAX_NOGAP 200 int nogapout = 0; int max_nogap = MAX_NOGAP; char nogap_inPath_[MAX_NOGAP][PATH_MAX + 1]; char *nogap_inPath[MAX_NOGAP]; int ret; int i; FILE *outf; lame_set_msgf(gf, &frontend_msgf); lame_set_errorf(gf, &frontend_errorf); lame_set_debugf(gf, &frontend_debugf); if (argc <= 1) { usage(stderr, argv[0]); /* no command-line args, print usage, exit */ return 1; } memset(inPath, 0, sizeof(inPath)); memset(nogap_inPath_, 0, sizeof(nogap_inPath_)); for (i = 0; i < MAX_NOGAP; ++i) { nogap_inPath[i] = &nogap_inPath_[i][0]; } /* parse the command line arguments, setting various flags in the * struct 'gf'. If you want to parse your own arguments, * or call libmp3lame from a program which uses a GUI to set arguments, * skip this call and set the values of interest in the gf struct. * (see the file API and lame.h for documentation about these parameters) */ ret = parse_args(gf, argc, argv, inPath, outPath, nogap_inPath, &max_nogap); if (ret < 0) { return ret == -2 ? 0 : 1; } if (global_ui_config.update_interval < 0.) global_ui_config.update_interval = 2.; if (outPath[0] != '\0' && max_nogap > 0) { strncpy(nogapdir, outPath, PATH_MAX + 1); nogapout = 1; } /* initialize input file. This also sets samplerate and as much other data on the input file as available in the headers */ if (max_nogap > 0) { /* for nogap encoding of multiple input files, it is not possible to * specify the output file name, only an optional output directory. */ parse_nogap_filenames(nogapout, nogap_inPath[0], outPath, nogapdir); outf = init_files(gf, nogap_inPath[0], outPath); } else { outf = init_files(gf, inPath, outPath); } if (outf == NULL) { return -1; } /* turn off automatic writing of ID3 tag data into mp3 stream * we have to call it before 'lame_init_params', because that * function would spit out ID3v2 tag data. */ lame_set_write_id3tag_automatic(gf, 0); /* Now that all the options are set, lame needs to analyze them and * set some more internal options and check for problems */ ret = lame_init_params(gf); if (ret < 0) { if (ret == -1) { display_bitrates(stderr); } error_printf("fatal error during initialization\n"); return ret; } if (global_ui_config.silent > 0) { global_ui_config.brhist = 0; /* turn off VBR histogram */ } if (lame_get_decode_only(gf)) { /* decode an mp3 file to a .wav */ ret = lame_decoder(gf, outf, inPath, outPath); } else if (max_nogap == 0) { /* encode a single input file */ ret = lame_encoder(gf, outf, 0, inPath, outPath); } else { /* encode multiple input files using nogap option */ for (i = 0; i < max_nogap; ++i) { int use_flush_nogap = (i != (max_nogap - 1)); if (i > 0) { parse_nogap_filenames(nogapout, nogap_inPath[i], outPath, nogapdir); /* note: if init_files changes anything, like samplerate, num_channels, etc, we are screwed */ outf = init_files(gf, nogap_inPath[i], outPath); /* reinitialize bitstream for next encoding. this is normally done * by lame_init_params(), but we cannot call that routine twice */ lame_init_bitstream(gf); } lame_set_nogap_total(gf, max_nogap); lame_set_nogap_currentindex(gf, i); ret = lame_encoder(gf, outf, use_flush_nogap, nogap_inPath[i], outPath); } } return ret; }
int lame_main(lame_t gf, int argc, char **argv) { unsigned char mp3buffer[LAME_MAXMP3BUFFER]; char inPath[PATH_MAX + 1]; char outPath[PATH_MAX + 1]; int Buffer[2][1152]; int maxx = 0, tmpx = 0; int ret; int wavsamples; int mp3bytes; FILE *outf; char ip[16]; unsigned int port = 5004; unsigned int ttl = 2; char dummy; if (argc <= 2) { console_printf("Encode (via LAME) to mp3 with RTP streaming of the output\n" "\n" " mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile\n" "\n" " examples:\n" " arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null\n" " arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3\n" "\n"); return 1; } switch (sscanf(argv[1], "%11[.0-9]:%u:%u%c", ip, &port, &ttl, &dummy)) { case 1: case 2: case 3: break; default: error_printf("Illegal destination selector '%s', must be ip[:port[:ttl]]\n", argv[1]); return -1; } rtp_initialization(); if (rtp_socket(ip, port, ttl)) { rtp_deinitialization(); error_printf("fatal error during initialization\n"); return 1; } lame_set_errorf(gf, &frontend_errorf); lame_set_debugf(gf, &frontend_debugf); lame_set_msgf(gf, &frontend_msgf); /* Remove the argumets that are rtp related, and then * parse the command line arguments, setting various flags in the * struct pointed to by 'gf'. If you want to parse your own arguments, * or call libmp3lame from a program which uses a GUI to set arguments, * skip this call and set the values of interest in the gf struct. * (see lame.h for documentation about these parameters) */ { int i; int argc_mod = argc-1; /* leaving out exactly one argument */ char** argv_mod = calloc(argc_mod, sizeof(char*)); argv_mod[0] = argv[0]; for (i = 2; i < argc; ++i) { /* leaving out argument number 1, parsed above */ argv_mod[i-1] = argv[i]; } parse_args(gf, argc_mod, argv_mod, inPath, outPath, NULL, NULL); free(argv_mod); } /* open the output file. Filename parsed into gf.inPath */ if (0 == strcmp(outPath, "-")) { lame_set_stream_binary_mode(outf = stdout); } else { if ((outf = lame_fopen(outPath, "wb+")) == NULL) { rtp_deinitialization(); error_printf("Could not create \"%s\".\n", outPath); return 1; } } /* open the wav/aiff/raw pcm or mp3 input file. This call will * open the file with name gf.inFile, try to parse the headers and * set gf.samplerate, gf.num_channels, gf.num_samples. * if you want to do your own file input, skip this call and set * these values yourself. */ if (init_infile(gf, inPath) < 0) { rtp_deinitialization(); fclose(outf); error_printf("Can't init infile '%s'\n", inPath); return 1; } /* Now that all the options are set, lame needs to analyze them and * set some more options */ ret = lame_init_params(gf); if (ret < 0) { if (ret == -1) display_bitrates(stderr); rtp_deinitialization(); fclose(outf); close_infile(); error_printf("fatal error during initialization\n"); return -1; } lame_print_config(gf); /* print useful information about options being used */ if (global_ui_config.update_interval < 0.) global_ui_config.update_interval = 2.; /* encode until we hit EOF */ while ((wavsamples = get_audio(gf, Buffer)) > 0) { /* read in 'wavsamples' samples */ levelmessage(maxvalue(Buffer), &maxx, &tmpx); mp3bytes = lame_encode_buffer_int(gf, /* encode the frame */ Buffer[0], Buffer[1], wavsamples, mp3buffer, sizeof(mp3buffer)); rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ } mp3bytes = lame_encode_flush(gf, /* may return one or more mp3 frame */ mp3buffer, sizeof(mp3buffer)); rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */ rtp_deinitialization(); fclose(outf); close_infile(); /* close the sound input file */ return 0; }
int main(int argc, char **argv) { int ret; lame_global_flags *gf; char outPath[PATH_MAX + 1]; char nogapdir[PATH_MAX + 1]; char inPath[PATH_MAX + 1]; /* add variables for encoder delay/padding */ int enc_delay = -1; int enc_padding = -1; /* support for "nogap" encoding of up to 200 .wav files */ #define MAX_NOGAP 200 int nogapout = 0; int max_nogap = MAX_NOGAP; char nogap_inPath_[MAX_NOGAP][PATH_MAX+1]; char* nogap_inPath[MAX_NOGAP]; int i; FILE *outf; #if macintosh argc = ccommand(&argv); #endif #if 0 /* rh 061207 the following fix seems to be a workaround for a problem in the parent process calling LAME. It would be better to fix the broken application => code disabled. */ #if defined(_WIN32) /* set affinity back to all CPUs. Fix for EAC/lame on SMP systems from "Todd Richmond" <*****@*****.**> */ typedef BOOL(WINAPI * SPAMFunc) (HANDLE, DWORD_PTR); SPAMFunc func; SYSTEM_INFO si; if ((func = (SPAMFunc) GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), "SetProcessAffinityMask")) != NULL) { GetSystemInfo(&si); func(GetCurrentProcess(), si.dwActiveProcessorMask); } #endif #endif #ifdef __EMX__ /* This gives wildcard expansion on Non-POSIX shells with OS/2 */ _wildcard(&argc, &argv); #endif memset(nogap_inPath_, 0, sizeof(nogap_inPath_)); for (i = 0; i < MAX_NOGAP; ++i) { nogap_inPath[i] = &nogap_inPath_[i][0]; } memset(inPath, 0, sizeof(inPath)); frontend_open_console(); /* initialize libmp3lame */ input_format = sf_unknown; if (NULL == (gf = lame_init())) { error_printf("fatal error during initialization\n"); frontend_close_console(); return 1; } lame_set_errorf(gf, &frontend_errorf); lame_set_debugf(gf, &frontend_debugf); lame_set_msgf(gf, &frontend_msgf); if (argc <= 1) { usage(stderr, argv[0]); /* no command-line args, print usage, exit */ lame_close(gf); frontend_close_console(); return 1; } /* parse the command line arguments, setting various flags in the * struct 'gf'. If you want to parse your own arguments, * or call libmp3lame from a program which uses a GUI to set arguments, * skip this call and set the values of interest in the gf struct. * (see the file API and lame.h for documentation about these parameters) */ parse_args_from_string(gf, getenv("LAMEOPT"), inPath, outPath); ret = parse_args(gf, argc, argv, inPath, outPath, nogap_inPath, &max_nogap); if (ret < 0) { lame_close(gf); frontend_close_console(); return ret == -2 ? 0 : 1; } if (update_interval < 0.) update_interval = 2.; if (outPath[0] != '\0' && max_nogap > 0) { strncpy(nogapdir, outPath, PATH_MAX + 1); nogapout = 1; } /* initialize input file. This also sets samplerate and as much other data on the input file as available in the headers */ if (max_nogap > 0) { /* for nogap encoding of multiple input files, it is not possible to * specify the output file name, only an optional output directory. */ parse_nogap_filenames(nogapout, nogap_inPath[0], outPath, nogapdir); outf = init_files(gf, nogap_inPath[0], outPath, &enc_delay, &enc_padding); } else { outf = init_files(gf, inPath, outPath, &enc_delay, &enc_padding); } if (outf == NULL) { lame_close(gf); frontend_close_console(); return -1; } /* turn off automatic writing of ID3 tag data into mp3 stream * we have to call it before 'lame_init_params', because that * function would spit out ID3v2 tag data. */ lame_set_write_id3tag_automatic(gf, 0); /* Now that all the options are set, lame needs to analyze them and * set some more internal options and check for problems */ i = lame_init_params(gf); if (i < 0) { if (i == -1) { display_bitrates(stderr); } error_printf("fatal error during initialization\n"); lame_close(gf); frontend_close_console(); return i; } if (silent > 0) { brhist = 0; /* turn off VBR histogram */ } if (lame_get_decode_only(gf)) { /* decode an mp3 file to a .wav */ if (mp3_delay_set) lame_decoder(gf, outf, mp3_delay, inPath, outPath, &enc_delay, &enc_padding); else lame_decoder(gf, outf, 0, inPath, outPath, &enc_delay, &enc_padding); } else { if (max_nogap > 0) { /* * encode multiple input files using nogap option */ for (i = 0; i < max_nogap; ++i) { int use_flush_nogap = (i != (max_nogap - 1)); if (i > 0) { parse_nogap_filenames(nogapout, nogap_inPath[i], outPath, nogapdir); /* note: if init_files changes anything, like samplerate, num_channels, etc, we are screwed */ outf = init_files(gf, nogap_inPath[i], outPath, &enc_delay, &enc_padding); /* reinitialize bitstream for next encoding. this is normally done * by lame_init_params(), but we cannot call that routine twice */ lame_init_bitstream(gf); } brhist_init_package(gf); lame_set_nogap_total(gf, max_nogap); lame_set_nogap_currentindex(gf, i); ret = lame_encoder(gf, outf, use_flush_nogap, nogap_inPath[i], outPath); fclose(outf); /* close the output file */ close_infile(); /* close the input file */ } } else { /* * encode a single input file */ brhist_init_package(gf); ret = lame_encoder(gf, outf, 0, inPath, outPath); fclose(outf); /* close the output file */ close_infile(); /* close the input file */ } } lame_close(gf); frontend_close_console(); return ret; }
void *encode(void *init) { char file[256]; int fd1 = -1, fd2 = -1, fd_out = -1; uint32_t i, k; int16_t *b0 = 0, *b1 = 0, *b2 = 0; rec_ctx *ctx = (rec_ctx *) init; #ifdef USING_LAME lame_global_flags *gfp; #endif log_info("in encode thread"); pthread_join(ctx->rec1,0); pthread_join(ctx->rec2,0); log_info("recorder threads complete, encoding"); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); fd1 = open(file,O_RDONLY); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); fd2 = open(file,O_RDONLY); if(fd1 < 0 || fd2 < 0) { if(fd1 >= 0) { close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file); } if(fd2 >= 0) { close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file); } log_err("encode: input file not found"); return 0; } #ifdef USING_LAME if(ctx->ismp3) sprintf(file, OUT_DIR "/%s.mp3",ctx->cur_file); else #endif sprintf(file, OUT_DIR "/%s.wav",ctx->cur_file); fd_out = open(file,O_CREAT|O_TRUNC|O_WRONLY); if(fd_out < 0) { log_err("encode: cannot open output file %s",file); close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file); close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file); return 0; } i = (uint32_t) lseek(fd1,0,SEEK_END); k = (uint32_t) lseek(fd2,0,SEEK_END); lseek(fd1,0,SEEK_SET); lseek(fd2,0,SEEK_SET); if(i != k) { log_info("file sizes mismatch"); if(i > k) i = k; } i &= ~1; if(i == 0) { log_err("zero size input file"); close(fd_out); unlink(file); close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file); close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file); return 0; } #ifdef USING_LAME if(ctx->ismp3) { gfp = lame_init(); lame_set_errorf(gfp,lame_error_handler); lame_set_debugf(gfp,lame_error_handler); lame_set_msgf(gfp,lame_error_handler); lame_set_num_channels(gfp,2); lame_set_in_samplerate(gfp,8000); lame_set_brate(gfp,64); /* compress 1:4 */ lame_set_mode(gfp,0); /* mode = stereo */ lame_set_quality(gfp,2); /* 2=high 5 = medium 7=low */ if(lame_init_params(gfp) < 0) { log_err("encode: failed to init lame"); close(fd_out); unlink(file); close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file); close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file); return 0; } #define CHSZ (512*1024) #define OCHSZ (5*(CHSZ/8)+7200) b0 = (int16_t *) malloc(OCHSZ); b1 = (int16_t *) malloc(CHSZ); b2 = (int16_t *) malloc(CHSZ); if(!b0 || !b1 || !b2) { log_err("encode: out of memory"); if(b0) free(b0); if(b1) free(b1); if(b2) free(b2); close(fd_out); unlink(file); close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file); close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file); return 0; } k = 0; do { int ret = 0; uint32_t j = 0, count = 0; unsigned char *c1,*c2; for(c1 = (unsigned char*) b1, c2 = (unsigned char*) b2; count < CHSZ; c1 += ret, c2 += ret) { j = (k + RSZ > i) ? i - k : RSZ; ret = read(fd1,c1,j); if(ret < 0) break; ret = read(fd2,c2,j); if(ret < 0) break; k += ret; count += ret; if(k == i) break; } if(ret < 0) break; if(count) { ret = lame_encode_buffer(gfp,b1,b2,count/2,(unsigned char *)b0,OCHSZ); if(ret < 0) break; c1 = (unsigned char *) b0; count = ret; for(j = 0; j < count; j += RSZ, c1 += ret) { ret = (j + RSZ > count) ? count - j : RSZ; write(fd_out,c1,ret); } } } while(k < i); i = (uint32_t) lame_encode_flush(gfp,(unsigned char *)b0,OCHSZ); if(i) write(fd_out,b0,i); lame_close(gfp); } else { #endif b0 = (int16_t *) malloc(RSZ*2); b1 = (int16_t *) malloc(RSZ); b2 = (int16_t *) malloc(RSZ); if(!b0 || !b1 || !b2) { log_err("encode: out of memory"); if(b0) free(b0); if(b1) free(b1); if(b2) free(b2); close(fd_out); unlink(file); close(fd1); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file); close(fd2); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file); return 0; } wavhdr.data_sz = i*2; wavhdr.riff_sz = i*2 + 36; write(fd_out,&wavhdr,sizeof(wavhdr)); k = 0; while(1) { uint32_t j, count = (k + RSZ > i) ? i - k : RSZ; if(read(fd1,b1,count) < 0) break; if(read(fd2,b2,count) < 0) break; for(j = 0; j < count/2; j++) { b0[2*j] = b1[j]; b0[2*j+1] = b2[j]; } write(fd_out,b0,count*2); k += count; if(k == i) break; } #ifdef USING_LAME } #endif close(fd1); close(fd2); close(fd_out); free(b0); free(b1); free(b2); log_info("encoding complete"); sprintf(file, OUT_DIR "/%s-up",ctx->cur_file); unlink(file); sprintf(file, OUT_DIR "/%s-dn",ctx->cur_file); unlink(file); free(ctx->x); free(ctx); return 0; }
int CEncoderLame::prepare( const sp<IMediaSource>& pMediaSource_in, const sp<IAudioSink>& pAudioSink_out, const sp<AMessage>& pOption_in ) { AUTO_LOG(); if (m_pGobalFlags != NULL) { RETURN(ALREADY_EXISTS); } CHECK_PTR_EXT(pMediaSource_in, BAD_VALUE); CHECK_PTR_EXT(pAudioSink_out, BAD_VALUE); sp<MetaData> pMeta = pMediaSource_in->getFormat(); CHECK_PTR_EXT(pMeta, BAD_VALUE); m_pGobalFlags = lame_init(); CHECK_PTR_EXT(m_pGobalFlags, BAD_VALUE); lame_set_errorf(m_pGobalFlags, CEncoderLame::errorf); lame_set_debugf(m_pGobalFlags, CEncoderLame::debugf); lame_set_msgf(m_pGobalFlags, CEncoderLame::msgf); id3tag_init(m_pGobalFlags); // TO DO // pass the user option to encoder //if (pOption_in != NULL) { //} int ret = OK; bool chk = false; int32_t iChannelNum = 0; chk = pMeta->findInt32(kKeyChannelCount, &iChannelNum); CHECK_IS_EXT((true == chk), UNKNOWN_ERROR); ret = lame_set_num_channels(m_pGobalFlags, iChannelNum); CHECK_IS_EXT((ret == OK), ret); int32_t iSampleRate = 0; chk = pMeta->findInt32(kKeySampleRate, &iSampleRate); CHECK_IS_EXT((true == chk), UNKNOWN_ERROR); ret = lame_set_in_samplerate(m_pGobalFlags, iSampleRate); CHECK_IS_EXT((ret == OK), ret); int32_t iBitsPerSample = 0; chk = pMeta->findInt32(kKeyBitsPerSample, &iBitsPerSample); CHECK_IS_EXT((true == chk), UNKNOWN_ERROR); int32_t iDataSize = 0; chk = pMeta->findInt32(kKeyDataSize, &iDataSize); CHECK_IS_EXT((true == chk), UNKNOWN_ERROR); ret = lame_set_num_samples(m_pGobalFlags, iDataSize / (iChannelNum * ((iBitsPerSample + 7) / 8))); CHECK_IS_EXT((ret == OK), ret); lame_set_write_id3tag_automatic(m_pGobalFlags, 0); ret = lame_init_params(m_pGobalFlags); CHECK_IS_EXT((ret == OK), ret); size_t id3v2_size = lame_get_id3v2_tag(m_pGobalFlags, 0, 0); if (id3v2_size > 0) { unsigned char *id3v2tag = new unsigned char[id3v2_size]; if (id3v2tag != 0) { int iTagSz = lame_get_id3v2_tag(m_pGobalFlags, id3v2tag, id3v2_size); int iWrite = (int) pAudioSink_out->write(id3v2tag, iTagSz); delete(id3v2tag); CHECK_IS_EXT((iTagSz == iWrite), UNKNOWN_ERROR); } } RETURN(OK); }
static gint mp3_open(void) { int imp3; gfp = lame_init(); if (gfp == NULL) return 0; /* setup id3 data */ id3tag_init(gfp); if (tuple) { /* XXX write UTF-8 even though libmp3lame does id3v2.3. --yaz */ lameid3.track_name = tuple_get_str (tuple, FIELD_TITLE, NULL); id3tag_set_title(gfp, lameid3.track_name); lameid3.performer = tuple_get_str (tuple, FIELD_ARTIST, NULL); id3tag_set_artist(gfp, lameid3.performer); lameid3.album_name = tuple_get_str (tuple, FIELD_ALBUM, NULL); id3tag_set_album(gfp, lameid3.album_name); lameid3.genre = tuple_get_str (tuple, FIELD_GENRE, NULL); id3tag_set_genre(gfp, lameid3.genre); lameid3.year = str_printf ("%d", tuple_get_int (tuple, FIELD_YEAR, NULL)); id3tag_set_year(gfp, lameid3.year); lameid3.track_number = str_printf ("%d", tuple_get_int (tuple, FIELD_TRACK_NUMBER, NULL)); id3tag_set_track(gfp, lameid3.track_number); if (force_v2_val) { id3tag_add_v2(gfp); } if (only_v1_val) { id3tag_v1_only(gfp); } if (only_v2_val) { id3tag_v2_only(gfp); } } /* input stream description */ lame_set_in_samplerate(gfp, input.frequency); lame_set_num_channels(gfp, input.channels); /* Maybe implement this? */ /* lame_set_scale(lame_global_flags *, float); */ lame_set_out_samplerate(gfp, out_samplerate_val); /* general control parameters */ lame_set_bWriteVbrTag(gfp, toggle_xing_val); lame_set_quality(gfp, algo_quality_val); if (audio_mode_val != 4) { AUDDBG("set mode to %d\n", audio_mode_val); lame_set_mode(gfp, audio_mode_val); } lame_set_errorf(gfp, lame_debugf); lame_set_debugf(gfp, lame_debugf); lame_set_msgf(gfp, lame_debugf); if (enc_toggle_val == 0 && vbr_on == 0) lame_set_brate(gfp, bitrate_val); else if (vbr_on == 0) lame_set_compression_ratio(gfp, compression_val); /* frame params */ lame_set_copyright(gfp, mark_copyright_val); lame_set_original(gfp, mark_original_val); lame_set_error_protection(gfp, error_protect_val); lame_set_strict_ISO(gfp, enforce_iso_val); if (vbr_on != 0) { if (vbr_type == 0) lame_set_VBR(gfp, 2); else lame_set_VBR(gfp, 3); lame_set_VBR_q(gfp, vbr_quality_val); lame_set_VBR_mean_bitrate_kbps(gfp, abr_val); lame_set_VBR_min_bitrate_kbps(gfp, vbr_min_val); lame_set_VBR_max_bitrate_kbps(gfp, vbr_max_val); lame_set_VBR_hard_min(gfp, enforce_min_val); } /* not to write id3 tag automatically. */ lame_set_write_id3tag_automatic(gfp, 0); if (lame_init_params(gfp) == -1) return 0; /* write id3v2 header */ imp3 = lame_get_id3v2_tag(gfp, encbuffer, sizeof(encbuffer)); if (imp3 > 0) { write_output(encbuffer, imp3); id3v2_size = imp3; } else { id3v2_size = 0; } write_buffer = NULL; write_buffer_size = 0; return 1; }
bool OutLame::apply_profile() { if(enc_flags) lame_close(enc_flags); enc_flags = lame_init(); lame_set_errorf(enc_flags,(void (*)(const char*, va_list))error); lame_set_debugf(enc_flags,(void (*)(const char*, va_list))func); lame_set_msgf(enc_flags,(void (*)(const char*, va_list))act); lame_set_num_samples(enc_flags,OUT_CHUNK); lame_set_num_channels(enc_flags,2); // the mixed input stream is stereo lame_set_in_samplerate(enc_flags,SAMPLE_RATE); // the mixed input stream is 44khz lame_set_error_protection(enc_flags,1); // 2 bytes per frame for a CRC checksum lame_set_compression_ratio(enc_flags,0); lame_set_quality(enc_flags,2); // 1..9 1=best 9=worst (suggested: 2, 5, 7) // lame_set_VBR(enc_flags,vbr_abr); /* BITRATE */ lame_set_brate(enc_flags,bps()); Shouter *ice = (Shouter*)icelist.begin(); while(ice) { char tmp[256]; snprintf(tmp,256,"%u",bps()); ice->bps( tmp ); snprintf(tmp,256,"%u",freq()); ice->freq( tmp ); snprintf(tmp,256,"%u",channels()); ice->channels( tmp ); ice = (Shouter*)ice->next; } lame_set_out_samplerate(enc_flags,freq()); /* CHANNELS mode 2 (double channel) is unsupported */ int mode; switch( channels() ) { /* 0,1,2,3 stereo,jstereo,dual channel,mono */ case 1: mode = 3; break; case 2: mode = 1; break; default: mode = 3; break; } lame_set_mode(enc_flags,(MPEG_mode_e)mode); /* in case of VBR func("reversed quality is %i, guessed bps %i",(int)fabs( 10 - quality()),bps()); lame_set_VBR_q(enc_flags,(int)fabs( 10 - quality() )); lame_set_VBR_mean_bitrate_kbps(enc_flags,bps()); */ /* lame chooses for us frequency filtering when values are 0 */ lame_set_lowpassfreq(enc_flags,lowpass()); lame_set_highpassfreq(enc_flags,highpass()); int res = lame_init_params(enc_flags); if(res<0) { error("lame_init_params failed"); lame_close(enc_flags); enc_flags = NULL; } return (res<0)?false:true; }