/***************************************************************************** * MPG123Open *****************************************************************************/ static int MPG123Open( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; /* Create our mpg123 handle */ if( ( p_sys->p_handle = mpg123_new( NULL, NULL ) ) == NULL ) { msg_Err( p_dec, "mpg123 error: can't create handle" ); return VLC_EGENERIC; } /* Open a new bitstream */ if( mpg123_open_feed( p_sys->p_handle ) != MPG123_OK ) { msg_Err( p_dec, "mpg123 error: can't open feed" ); mpg123_delete( p_sys->p_handle ); return VLC_EGENERIC; } /* Disable resync stream after error */ mpg123_param( p_sys->p_handle, MPG123_ADD_FLAGS, MPG123_NO_RESYNC, 0 ); /* Setup output format */ mpg123_format_none( p_sys->p_handle ); int i_ret = MPG123_OK; if( p_dec->fmt_in.audio.i_rate != 0 ) { i_ret = mpg123_format( p_sys->p_handle, p_dec->fmt_in.audio.i_rate, MPG123_MONO | MPG123_STEREO, MPG123_ENC_FLOAT_32 ); } else { /* The rate from the input is unknown. Tell mpg123 to accept all rates * to avoid conversion on their side */ static const long mp3_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, }; for( size_t i = 0; i < sizeof(mp3_rates) / sizeof(*mp3_rates) && i_ret == MPG123_OK; ++i ) { i_ret = mpg123_format( p_sys->p_handle, mp3_rates[i], MPG123_MONO | MPG123_STEREO, MPG123_ENC_FLOAT_32 ); } } if( i_ret != MPG123_OK ) { msg_Err( p_dec, "mpg123 error: %s", mpg123_strerror( p_sys->p_handle ) ); mpg123_close( p_sys->p_handle ); mpg123_delete( p_sys->p_handle ); return VLC_EGENERIC; } p_sys->b_opened = true; return VLC_SUCCESS; }
SharedPtr<Decoder> Mpg123DecoderFactory::createDecoder(SharedPtr<std::istream> file) { if(!mIsInited) return SharedPtr<Decoder>(nullptr); mpg123_handle *mpg123 = mpg123_new(0, 0); if(mpg123) { if(mpg123_replace_reader_handle(mpg123, r_read, r_lseek, 0) == MPG123_OK && mpg123_open_handle(mpg123, file.get()) == MPG123_OK) { int enc, channels; long srate; if(mpg123_getformat(mpg123, &srate, &channels, &enc) == MPG123_OK) { if((channels == 1 || channels == 2) && srate > 0 && mpg123_format_none(mpg123) == MPG123_OK && mpg123_format(mpg123, srate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK) { // All OK return SharedPtr<Decoder>(new Mpg123Decoder(file, mpg123, channels, srate)); } } mpg123_close(mpg123); } mpg123_delete(mpg123); } return SharedPtr<Decoder>(nullptr); }
VALUE rb_mpg123_new(VALUE klass, VALUE filename) { int err = MPG123_OK; mpg123_handle *mh; VALUE mpg123; long rate; int channels, encoding; Check_Type(filename, T_STRING); if ((mh = mpg123_new(NULL, &err)) == NULL) { rb_raise(rb_eStandardError, "%s", mpg123_plain_strerror(err)); } mpg123_param(mh, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT, 0.); if (mpg123_open(mh, (char*) RSTRING_PTR(filename)) != MPG123_OK || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { rb_raise(rb_eStandardError, "%s", mpg123_strerror(mh)); } if (encoding != MPG123_ENC_FLOAT_32) { rb_raise(rb_eStandardError, "bad encoding"); } mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); VALUE new_mpg123 = Data_Wrap_Struct(rb_cMpg123, 0, cleanup, mh); rb_iv_set(new_mpg123, "@file", filename); return new_mpg123; }
int mp3file_determineStats(MP3File *mp3) { if (mp3 == NULL) return; int encoding; mpg123_handle* mh = mp3->handle; int err = mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding); if (err == MPG123_NEED_MORE) return err; if (err != MPG123_OK) { printerr("mpg123_getformat", err); return err; } mpg123_format_none(mh); mpg123_format(mh, mp3->rate, mp3->channels, encoding); mp3->num_samples = mpg123_length(mh); mp3->samples_per_frame = mpg123_spf(mh); mp3->secs_per_frame = mpg123_tpf(mh); if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0) mp3->num_frames = 0; else mp3->num_frames = mp3->num_samples / mp3->samples_per_frame; if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0 || mp3->secs_per_frame < 0) mp3->duration = 0; else mp3->duration = mp3->num_samples / mp3->samples_per_frame * mp3->secs_per_frame; return err; }
MP3Decoder::MP3Decoder(const char* filename) { f = fopen(filename,"rb"); fseek(f,0,SEEK_END); size_t size = ftell(f); cbuf = (uchar*)malloc(size*24); size_t buffer_size = 0; size_t done = 0; rate = 0; channels = 0; encoding = 0; int err = MPG123_OK; err = mpg123_init(); if(err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL) { QMessageBox::critical(0,QString("MP3 decoding error!"),QString("Basic setup goes wrong: ")+QString(mpg123_plain_strerror(err))); cleanup(mh); return ; } /* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */ if( mpg123_open(mh, filename) != MPG123_OK /* Peek into track and get first output format. */ || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ) { QMessageBox::critical(0,QString("MP3 decoding error!"),QString("Error decoding mp3 file: ")+QString(mpg123_strerror(mh))); cleanup(mh); return ; } if(encoding != MPG123_ENC_SIGNED_16 && encoding != MPG123_ENC_FLOAT_32) { /* Signed 16 is the default output format anyways; it would actually by only different if we forced it. So this check is here just for this explanation. */ cleanup(mh); QMessageBox::critical(0,QString("MP3 decoding error!"),"Bad encoding: 0x"+QString::number(encoding,16)); return; } /* Ensure that this output format will not change (it could, when we allow it). */ mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); buffer_size = mpg123_outblock(mh); cdone=0; buffer = (unsigned char*)malloc( buffer_size ); do { err = mpg123_read( mh, buffer, buffer_size, &done ); if(done<1)qDebug()<<"Error while reading mp3: "<<mpg123_errcode(mh); else memcpy(cbuf+cdone,buffer,done); cdone+=done; } while (err==MPG123_OK); cbuf[cdone-1]=0; if(err != MPG123_DONE){ fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n", err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) ); QMessageBox::critical(0,QString("MP3 decoding error!"),QString("MP3 Decoding ended prematurely: %1").arg(err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) )); return; } }
Mpg123Input::Mpg123Input(const QString &fileName) { handle=new Handle; QByteArray fName=QFile::encodeName(fileName); bool ok=false; int result; handle->mpg123 = mpg123_new(NULL, &result); if (handle->mpg123 && MPG123_OK==mpg123_open(handle->mpg123, fName.constData()) && MPG123_OK==mpg123_getformat(handle->mpg123, &handle->rate, &handle->channels, &handle->encoding) && MPG123_OK==mpg123_format_none(handle->mpg123) && MPG123_OK==mpg123_format(handle->mpg123, handle->rate, handle->channels, MPG123_ENC_FLOAT_32)) { mpg123_close(handle->mpg123); if (MPG123_OK==mpg123_open(handle->mpg123, fName.constData()) && MPG123_OK==mpg123_getformat(handle->mpg123, &handle->rate, &handle->channels, &handle->encoding)) { ok=true; } } if (!ok) { if (handle->mpg123) { mpg123_close(handle->mpg123); mpg123_delete(handle->mpg123); handle->mpg123 = NULL; } delete handle; handle = 0; } }
void * in_mp3_open(char *file) { mpg123_handle *m; int channels, encoding, r; long rate; channels = encoding = 0; rate = 0; m = mpg123_new(NULL, &r); assert(m != NULL); /* verbosity */ mpg123_param(m, MPG123_VERBOSE, 1, 0); r = mpg123_open(m, file); if (r != MPG123_OK) return NULL; assert(m != NULL); assert(mpg123_getformat(m, &rate, &channels, &encoding) == MPG123_OK); mpg123_format_none(m); mpg123_format(m, rate, channels, encoding); return m; }
int fm_player_open(fm_player_t *pl, fm_player_config_t *config) { pl->config = *config; if (strcmp(config->driver, "pifm") == 0) { float f = atof(config->dev); if (f < 1) f = 102.4; printf("Player audio driver: pifm\n"); printf("Player sample rate: %d Hz\n", config->rate); printf("Player FM fequency: %f Hz\n", f); config->channels = 1; fm_setup_fm(); fm_setup_dma(f); } else { ao_sample_format ao_fmt; ao_fmt.rate = config->rate; ao_fmt.channels = config->channels; ao_fmt.bits = mpg123_encsize(config->encoding) * 8; ao_fmt.byte_format = AO_FMT_NATIVE; ao_fmt.matrix = 0; int driver = ao_driver_id(config->driver); if (driver == -1) { return -1; } ao_info *driver_info = ao_driver_info(driver); printf("Player audio driver: %s\n", driver_info->name); printf("Player sample rate: %d Hz\n", pl->config.rate); ao_option *options = NULL; if (config->dev[0] != '\0') { ao_append_option(&options, "dev", config->dev); } pl->dev = ao_open_live(driver, &ao_fmt, options); ao_free_options(options); if (pl->dev == NULL) return -1; } pl->mh = mpg123_new(NULL, NULL); mpg123_format_none(pl->mh); mpg123_format(pl->mh, config->rate, config->channels, config->encoding); pl->curl = curl_easy_init(); curl_easy_setopt(pl->curl, CURLOPT_WRITEFUNCTION, download_callback); curl_easy_setopt(pl->curl, CURLOPT_WRITEDATA, pl); pl->tid_ack = 0; pthread_mutex_init(&pl->mutex_status, NULL); pthread_cond_init(&pl->cond_play, NULL); pl->status = FM_PLAYER_STOP; return 0; }
bool ofxSoundFile::mpg123Open(string path){ int err; mp3File = mpg123_new(NULL,&err); mpg123_param(mp3File, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT, 0.); if(mpg123_open(mp3File,path.c_str())!=MPG123_OK){ ofLogError() << "ofxSoundFile: couldnt read " + path; return false; } int encoding; long int rate; mpg123_getformat(mp3File,&rate,&channels,&encoding); if(encoding!=MPG123_ENC_SIGNED_16 && encoding != MPG123_ENC_FLOAT_32){ ofLogError() << "ofxSoundFile: unsupported encoding"; return false; } mpg123_format_none(mp3File); mpg123_format(mp3File, rate, channels, encoding); samplerate = rate; mpg123_seek(mp3File,0,SEEK_END); samples = mpg123_tell(mp3File); mpg123_seek(mp3File,0,SEEK_SET); bitDepth = 16; //TODO:get real bitdepth;. }
void MusicPlayer::play(const char *filename) { #ifdef USE_OGG stb_vorbis_close(v); stb_vorbis_alloc t; t.alloc_buffer=this->buf; t.alloc_buffer_length_in_bytes=STB_BUFSIZE; // stb_vorbis has char* pointer even though it is not really writing to buffer v = stb_vorbis_open_filename((char *)filename, &error, &t); #endif #ifdef USE_MP3 mpg123_close(mh); error = mpg123_open(mh, filename); if (!error) { error = mpg123_getformat(mh, &rate, &channels, &encoding); rate = AUDIO_FREQUENCY; channels = 2; mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); } #endif }
void input_mpg123::open(std::string path) { int err; int encoding; handle = mpg123_new(NULL, &err); if (handle == NULL) { throw input_error(mpg123_plain_strerror(err)); } if ((err = mpg123_open(handle, path.c_str())) != MPG123_OK) { throw input_error(mpg123_plain_strerror(err)); } if ((err = mpg123_getformat(handle, &_rate, &_channels, &encoding)) != MPG123_OK) { throw input_error(mpg123_plain_strerror(err)); } read_metadata(); /* force 16 bit format */ encoding = MPG123_ENC_SIGNED_16; mpg123_format_none(handle); mpg123_format(handle, _rate, _channels, encoding); double seconds_left; if ((err = mpg123_position(handle, 0, 0, NULL, NULL, NULL, &seconds_left)) != MPG123_OK) { throw input_error(mpg123_plain_strerror(err)); } this->_encoding = encoding; this->_length = seconds_left; }
bool Mp3Decoder::afterOpen() { int encoding; long numberOfSamplesPerSecond; int res = mpg123_getformat(_handle, &numberOfSamplesPerSecond, &_numberOfChannels, &encoding); if(res != MPG123_OK) { printf("mpg123_getformat failed\n"); return false; } if(encoding != MPG123_ENC_SIGNED_16) { printf("encoding != MPG123_ENC_SIGNED_16\n"); return false; } /* Ensure that this output format will not change (it could, when we allow it). */ res = mpg123_format_none(_handle); assert(res == MPG123_OK); res = mpg123_format(_handle, numberOfSamplesPerSecond, _numberOfChannels, encoding); assert(res == MPG123_OK); _numberOfSamplesPerSecond = numberOfSamplesPerSecond; _numberOfBitsPerSample = 16; dprintf("\nsample rate: %d\n", _numberOfSamplesPerSecond); return true; }
Mpg123Decoder::Mpg123Decoder(Data *data, const std::string &ext, int bufferSize) : Decoder(data, ext, bufferSize) , decoder_file(data) , handle(0) , channels(MPG123_STEREO) , duration(-2.0) { int ret = 0; if (!inited) { ret = mpg123_init(); if (ret != MPG123_OK) throw love::Exception("Could not initialize mpg123."); inited = (ret == MPG123_OK); } // Intialize the handle. handle = mpg123_new(nullptr, nullptr); if (handle == nullptr) throw love::Exception("Could not create decoder."); // Suppressing all mpg123 messages. mpg123_param(handle, MPG123_ADD_FLAGS, MPG123_QUIET, 0); try { ret = mpg123_replace_reader_handle(handle, &read_callback, &seek_callback, &cleanup_callback); if (ret != MPG123_OK) throw love::Exception("Could not set decoder callbacks."); ret = mpg123_open_handle(handle, &decoder_file); if (ret != MPG123_OK) throw love::Exception("Could not open decoder."); // mpg123_getformat should be able to tell us the properties of the stream's first frame. long rate = 0; ret = mpg123_getformat(handle, &rate, &channels, nullptr); if (ret == MPG123_ERR) throw love::Exception("Could not get stream information."); // I forgot what this was about. if (channels == 0) channels = 2; // Force signed 16-bit output. mpg123_param(handle, MPG123_FLAGS, (channels == 2 ? MPG123_FORCE_STEREO : MPG123_MONO_MIX), 0); mpg123_format_none(handle); mpg123_format(handle, rate, channels, MPG123_ENC_SIGNED_16); sampleRate = rate; } catch (love::Exception &) { mpg123_delete(handle); throw; } }
void mpgplayer::run() { if(mpg123_init() != MPG123_OK) qDebug("Error initilizing mpg123"); const char **test = mpg123_supported_decoders(); int error; mpg123_handle *mh = mpg123_new(test[0],&error); if(!mpg123_feature(MPG123_FEATURE_DECODE_LAYER3)) { qDebug("You do not seem to have mp3 decoding support"); return; } mpg123_format_none(mh); if(mpg123_format(mh,samplerate,MPG123_STEREO,MPG123_ENC_SIGNED_16)!=MPG123_OK) qDebug("Error in initilizing format decoder"); qDebug(test[0]); mpg123_open(mh,"/home/eli/Projects/groove-evan/Animal.mp3"); net = TData; pa_simple *s; pa_sample_spec ss; ss.format = PA_SAMPLE_S16NE; ss.rate = samplerate; ss.channels = 2; s =pa_simple_new(NULL,"Groove",PA_STREAM_PLAYBACK ,NULL,"Music",&ss,NULL,NULL,NULL); unsigned char bytes[1024]; size_t bsize = 1024; size_t done = 0; bool stop = false; playing=true; while(!stop) { switch(net) { case TWait: usleep(100); break; case TData: if(mpg123_read(mh,bytes,bsize,&done)==MPG123_DONE) { net=TFinish; } pa_simple_write(s,bytes,done,&error); break; case TAbort: stop = true; break; case TFinish: pa_simple_drain(s,&error); stop = true; break; default: break; } } qDebug("Finsihed playback"); pa_simple_free(s); mpg123_exit(); }
bool Mpg123Decoder::SetFormat(int freq, AudioDecoder::Format fmt, int channels) { // mpg123 has a built-in pseudo-resampler, not needing SDL_ConvertAudio later // Remove all available conversion formats // Add just one format to force mpg123 pseudo-resampler work mpg123_format_none(handle.get()); err = mpg123_format(handle.get(), (long)freq, (int)channels, (int)format_to_mpg123_format(fmt)); if (err != MPG123_OK) { err = mpg123_format(handle.get(), (long)44100, (int)channels, (int)format_to_mpg123_format(fmt)); if (err != MPG123_OK) { mpg123_format(handle.get(), (long)44100, (int)2, (int)MPG123_ENC_SIGNED_16); } return false; } return err == MPG123_OK; }
void DecoderMPG123::setMPG123Format(int encoding) { int sample_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }; /* Ensure that this output format will not change (it could, when we allow it). */ mpg123_format_none(m_handle); for(unsigned int i = 0; i < sizeof(sample_rates)/sizeof(int); ++i) mpg123_format(m_handle, sample_rates[i], MPG123_MONO | MPG123_STEREO, encoding); m_mpg123_encoding = encoding; }
JNIEXPORT jlong JNICALL Java_com_axelby_podax_player_MPG123_openFile (JNIEnv *env, jclass c, jstring filename) { int err = MPG123_OK; mpg123_handle *mh = mpg123_new(NULL, &err); if (err == MPG123_OK && mh != NULL) { MP3File* mp3 = mp3file_init(mh); const char* fileString = (*env)->GetStringUTFChars(env, filename, NULL); err = mpg123_open(mh, fileString); (*env)->ReleaseStringUTFChars(env, filename, fileString); if (err == MPG123_OK) { int encoding; if (mpg123_getformat(mh, &mp3->rate, &mp3->channels, &encoding) == MPG123_OK) { if(encoding == MPG123_ENC_SIGNED_16) { // Signed 16 is the default output format anyway; // it would actually by only different if we forced it. // So this check is here just for this explanation. // Ensure that this output format will not change // (it could, when we allow it). mpg123_format_none(mh); mpg123_format(mh, mp3->rate, mp3->channels, encoding); mp3->buffer_size = mpg123_outblock(mh); mp3->buffer = (unsigned char*)malloc(mp3->buffer_size); mp3->num_samples = mpg123_length(mh); mp3->samples_per_frame = mpg123_spf(mh); mp3->secs_per_frame = mpg123_tpf(mh); if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0) mp3->num_frames = 0; else mp3->num_frames = mp3->num_samples / mp3->samples_per_frame; if (mp3->num_samples == MPG123_ERR || mp3->samples_per_frame < 0 || mp3->secs_per_frame < 0) mp3->duration = 0; else mp3->duration = mp3->num_samples / mp3->samples_per_frame * mp3->secs_per_frame; return (jlong)mp3; } } } mp3file_delete(mp3); } else { __android_log_write(ANDROID_LOG_INFO, "podax-jni", mpg123_plain_strerror(err)); } return 0; }
AudioSourceMpg123::AudioSourceMpg123(const char* filename) : AudioSource(filename) { rate_ = 0; channelCount_ = 0; sampleCount_ = 0; int err = MPG123_OK; mpg123_handle* mh = mpg123_new(NULL, &err); if (mh == NULL || err != MPG123_OK) return; /* if (mpg123_open(mh, filename) != MPG123_OK) { mpg123_delete(mh); return; } */ G_FILE* file = g_fopen(filename, "rb"); if (file == NULL) { mpg123_delete(mh); return; } mpg123_replace_reader_handle(mh, mpg123read, mpg123lseek, mpg123cleanup); if (mpg123_open_handle(mh, file) != MPG123_OK) { mpg123_delete(mh); return; } int channels = 0, encoding = 0; long rate = 0; if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { mpg123_delete(mh); return; } // Signed 16 is the default output format anyways (encoding == MPG123_ENC_SIGNED_16); // it would actually by only different if we forced it. // Ensure that this output format will not change (it could, when we allow it). mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); rate_ = rate; channelCount_ = channels; mpg123_scan(mh); sampleCount_ = mpg123_length(mh); mpg123_close(mh); mpg123_delete(mh); }
VALUE rb_mpg123_new(VALUE klass, VALUE filename, VALUE decideRate) { printf("Made it: 1\n"); int err = MPG123_OK; mpg123_handle *mh; printf("mh: "); printf("%d", mh); printf("\n"); VALUE mpg123; long rate; rate = decideRate; printf("rate: "); printf("%d", rate); printf("\n"); int channels, encoding; printf("Made it: 2\n"); printf("rate: "); printf("%d", rate); printf("\n"); Check_Type(filename, T_STRING); printf("Made it: 3\n"); printf("rate: "); printf("%d", rate); printf("\n"); if ((mh = mpg123_new(NULL, &err)) == NULL) { rb_raise(rb_eStandardError, "%s", mpg123_plain_strerror(err)); } printf("Made it: 4\n"); printf("rate: "); printf("%d", rate); printf("\n"); mpg123_param(mh, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT, 0.); printf("mpg123_open is: "); printf("%d", mpg123_open(mh, (char*) RSTRING_PTR(filename))); printf("\n"); printf("mh: "); printf("%d", mh); printf("\n"); printf("rate: "); printf("%d", rate); printf("\n"); printf("channels: "); printf("%d", channels); printf("\n"); printf("encoding: "); printf("%d", encoding); printf("\n"); printf("mpg123_getformat is: "); printf("%d", mpg123_getformat(mh, &rate, &channels, &encoding)); printf("\n"); printf("MPG123_OK is: "); printf("%d", MPG123_OK); printf("\n"); if (mpg123_open(mh, (char*) RSTRING_PTR(filename)) != MPG123_OK || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { rb_raise(rb_eStandardError, "%s", mpg123_strerror(mh)); } printf("Made it: 5"); if (encoding != MPG123_ENC_FLOAT_32) { rb_raise(rb_eStandardError, "bad encoding"); } printf("Made it: 6"); mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); printf("Made it: 7"); return Data_Wrap_Struct(rb_cMpg123, 0, cleanup, mh); }
static inline jlong wrapped_Java_com_badlogic_gdx_audio_io_Mpg123Decoder_openFile (JNIEnv* env, jobject object, jstring obj_filename, char* filename) { //@line:111 mpg123_handle *mh = NULL; int channels = 0, encoding = 0; long rate = 0; int err = MPG123_OK; err = mpg123_init(); if( err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL || mpg123_open(mh, filename) != MPG123_OK || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ) { fprintf( stderr, "Trouble with mpg123: %s\n", mh==NULL ? mpg123_plain_strerror(err) : mpg123_strerror(mh) ); cleanup(mh); return 0; } if(encoding != MPG123_ENC_SIGNED_16) { // Signed 16 is the default output format anyways; it would actually by only different if we forced it. // So this check is here just for this explanation. cleanup(mh); return 0; } // Ensure that this output format will not change (it could, when we allow it). mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); size_t buffer_size = mpg123_outblock( mh ); unsigned char* buffer = (unsigned char*)malloc(buffer_size); size_t done = 0; int samples = 0; Mp3File* mp3 = new Mp3File(); mp3->handle = mh; mp3->channels = channels; mp3->rate = rate; mp3->buffer = buffer; mp3->buffer_size = buffer_size; int length = mpg123_length( mh ); if( length == MPG123_ERR ) mp3->length = 0; else mp3->length = length / rate; return (jlong)mp3; }
static bool is_mp3(FILE *fp, struct file_type **ft) { mpg123_init(); int err; mpg123_handle *mh = mpg123_new(NULL, &err); if (mh == NULL) { fprintf(stderr, "Could not create mpg123 handle: %s\n", mpg123_plain_strerror(err)); return false; } long pos = ftell(fp); if (mpg123_open_fd(mh, fileno(fp)) != MPG123_OK) { fseek(fp, pos, SEEK_SET); return false; } mpg123_scan(mh); struct mpg123_frameinfo fi; mpg123_info(mh, &fi); if (mpg123_format(mh, fi.rate, MPG123_STEREO, MPG123_ENC_SIGNED_16) != MPG123_OK) { fseek(fp, pos, SEEK_SET); return false; } off_t length = mpg123_length(mh); struct mp3_format *fmt = calloc(sizeof(*fmt), 1); *ft = &fmt->ft; fmt->mh = mh; fmt->tpf = mpg123_tpf(mh); fmt->ft.channels = 2; fmt->ft.position = 0; fmt->ft.length = (length + (fi.rate / 2)) / fi.rate; fmt->ft.sample_rate = fi.rate; fmt->ft.sample_size = 2; fmt->ft.sample_type = ST_SIGNED_INTEGER_LE; fmt->ft.bitrate = (double)fi.abr_rate; return true; }
AudioStreamerMpg123::AudioStreamerMpg123(AudioSourceMpg123* source, int loops) : AudioStreamer(source, loops) { handle_ = NULL; int err = MPG123_OK; mpg123_handle* mh = mpg123_new(NULL, &err); if (mh == NULL || err != MPG123_OK) return; /* if (mpg123_open(mh, source->fileName()) != MPG123_OK) { mpg123_delete(mh); return; }*/ G_FILE* file = g_fopen(source->fileName(), "rb"); if (file == NULL) { mpg123_delete(mh); return; } mpg123_replace_reader_handle(mh, mpg123read, mpg123lseek, mpg123cleanup); if (mpg123_open_handle(mh, file) != MPG123_OK) { mpg123_delete(mh); return; } int channels = 0, encoding = 0; long rate = 0; if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { mpg123_delete(mh); return; } // Signed 16 is the default output format anyways (encoding == MPG123_ENC_SIGNED_16); // it would actually by only different if we forced it. // Ensure that this output format will not change (it could, when we allow it). mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); handle_ = mh; }
static uint8_t * ReadMP3(Sound_t * Sound, const uint8_t * InData, size_t FileSize){ mpg123_handle *mh; if(mpg123_init() != MPG123_OK || (mh = mpg123_new(NULL, NULL)) == NULL){ mpg123_exit(); return NULL; } long rate; int channels, encoding; unsigned samples; size_t OutSize; uint8_t * OutData; if(mpg123_format_none(mh) != MPG123_OK || mpg123_format(mh, 44100, MPG123_MONO | MPG123_STEREO, MPG123_ENC_SIGNED_16) != MPG123_OK || mpg123_open_feed(mh) != MPG123_OK || mpg123_feed(mh, InData, FileSize) != MPG123_OK || mpg123_set_filesize(mh, FileSize) != MPG123_OK || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK || (samples = mpg123_length(mh)) == 0 || (OutData = (uint8_t*) malloc(OutSize = samples * channels * 2)) == NULL ){ mpg123_close(mh); mpg123_delete(mh); mpg123_exit(); return NULL; } size_t decoded; mpg123_read(mh, OutData, OutSize, &decoded); mpg123_close(mh); mpg123_delete(mh); mpg123_exit(); if(decoded != OutSize){ free(OutData); return NULL; } Sound->Channels = channels; Sound->SamplingRate = rate; Sound->BitDepth = 16; Sound->Duration = samples; Sound->Data = OutData; return OutData; }
bool MPG123Decoder::open(FileReader &reader) { if(!inited) { if (!IsMPG123Present()) return false; if(mpg123_init() != MPG123_OK) return false; inited = true; } Reader = std::move(reader); { MPG123 = mpg123_new(NULL, NULL); if(mpg123_replace_reader_handle(MPG123, file_read, file_lseek, NULL) == MPG123_OK && mpg123_open_handle(MPG123, this) == MPG123_OK) { int enc, channels; long srate; if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK) { if((channels == 1 || channels == 2) && srate > 0 && mpg123_format_none(MPG123) == MPG123_OK && mpg123_format(MPG123, srate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK) { // All OK Done = false; return true; } } mpg123_close(MPG123); } mpg123_delete(MPG123); MPG123 = 0; } reader = std::move(Reader); // need to give it back. return false; }
inline void MP3Decoder::openFile(const char *filename) { mpg123_handle *mh = NULL; int channels = 0, encoding = 0; long rate = 0; int err = MPG123_OK; err = mpg123_init(); if( err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL || mpg123_open(mh, filename) != MPG123_OK || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ) { printf( "Trouble with mpg123: %s with file: %s\n", mh==NULL ? mpg123_plain_strerror(err) : mpg123_strerror(mh), filename); this->cleanup(mh); return; } // Ensure that this output format will not change (it could, when we allow it). mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); size_t buffer_size = mpg123_length(mh) * channels;//mpg123_outblock( mh ); printf("buffer size: %ld\n", buffer_size); unsigned char* buffer = (unsigned char*)malloc(buffer_size); size_t done = 0; int samples = 0; mp3File = MP3File(); mp3File.handle = mh; mp3File.channels = channels; mp3File.rate = rate; mp3File.buffer = buffer; mp3File.buffer_size = buffer_size; int length = mpg123_length( mh ); if( length == MPG123_ERR ) mp3File.length = 0; else mp3File.length = length / rate; }
/** * TODO */ JNIEXPORT jlong JNICALL Java_de_mpg123_MPG123Decoder_open (JNIEnv *env, jobject self, jstring path_to_file) { // Error code int err = MPG123_OK; // Properties int channels; long rate; long num_samples; int encoding; size_t buffer_size; // Create new mpg123 handle m_Mp3Decoder.m_mh = mpg123_new(NULL, &err); __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "mpg123_new: %p", m_Mp3Decoder.m_mh); if (err == MPG123_OK && m_Mp3Decoder.m_mh != NULL) { // Get the utf-8 string const char *file_path = env->GetStringUTFChars(path_to_file, JNI_FALSE); // Create new sound file and assign it to private Mp3Decoder field SoundFile *sound_file = new SoundFile(file_path); __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Sound file path: %s", sound_file->file_path); err = mpg123_open(m_Mp3Decoder.m_mh, sound_file->file_path); // The jni string can now be released //env->ReleaseStringUTFChars(path_to_file, file_path); if (err == MPG123_OK) { err = mpg123_getformat(m_Mp3Decoder.m_mh, &rate, &channels, &encoding); if (err == MPG123_OK) { // Reset internal format table and only allow specific encodings mpg123_format_none(m_Mp3Decoder.m_mh); // TODO: remove this: Force 32 bit float encoding //mp3->encoding = MPG123_ENC_FLOAT_32; encoding = MPG123_ENC_SIGNED_16; // Set fixed format mpg123_format(m_Mp3Decoder.m_mh, rate, channels, encoding); // Store the maximum buffer size that is possible // The buffer will be needed in the reading/decoding step buffer_size = mpg123_outblock(m_Mp3Decoder.m_mh); // Store number of samples of one channel of current track num_samples = mpg123_length(m_Mp3Decoder.m_mh); // TODO: if sound file init fails, what to do? // Everything was properly loaded with mpg123. Initialize sound file sound_file->init(channels, rate, num_samples, encoding, buffer_size); //__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "return sound file pointer: %p", // sound_file); return (jlong) sound_file; } else { __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Error: mpg123_getformat err: %i", err); __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Trouble with mpg123: %s", mpg123_strerror(m_Mp3Decoder.m_mh)); } } else { __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Error: mpg123_open err: %i", err); } delete sound_file; } __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Error: no proper initialization of mpg123lib."); return 0; }
static gboolean gst_mpg123_audio_dec_set_format (GstAudioDecoder * dec, GstCaps * input_caps) { /* Using the parsed information upstream, and the list of allowed caps * downstream, this code tries to find a suitable audio info. It is important * to keep in mind that the rate and number of channels should never deviate * from the one the bitstream has, otherwise mpg123 has to mix channels and/or * resample (and as its docs say, its internal resampler is very crude). The * sample format, however, can be chosen freely, because the MPEG specs do not * mandate any special format. Therefore, rate and number of channels are taken * from upstream (which parsed the MPEG frames, so the input_caps contain * exactly the rate and number of channels the bitstream actually has), while * the sample format is chosen by trying out all caps that are allowed by * downstream. This way, the output is adjusted to what the downstream prefers. * * Also, the new output audio info is not set immediately. Instead, it is * considered the "next audioinfo". The code waits for mpg123 to notice the new * format (= when mpg123_decode_frame() returns MPG123_AUDIO_DEC_NEW_FORMAT), * and then sets the next audioinfo. Otherwise, the next audioinfo is set too * soon, which may cause problems with mp3s containing several format headers. * One example would be an mp3 with the first 30 seconds using 44.1 kHz, then * the next 30 seconds using 32 kHz. Rare, but possible. * * STEPS: * * 1. get rate and channels from input_caps * 2. get allowed caps from src pad * 3. for each structure in allowed caps: * 3.1. take format * 3.2. if the combination of format with rate and channels is unsupported by * mpg123, go to (3), or exit with error if there are no more structures * to try * 3.3. create next audioinfo out of rate,channels,format, and exit */ int rate, channels; GstMpg123AudioDec *mpg123_decoder; GstCaps *allowed_srccaps; guint structure_nr; gboolean match_found = FALSE; mpg123_decoder = GST_MPG123_AUDIO_DEC (dec); g_assert (mpg123_decoder->handle != NULL); mpg123_decoder->has_next_audioinfo = FALSE; /* Get rate and channels from input_caps */ { GstStructure *structure; gboolean err = FALSE; /* Only the first structure is used (multiple * input caps structures don't make sense */ structure = gst_caps_get_structure (input_caps, 0); if (!gst_structure_get_int (structure, "rate", &rate)) { err = TRUE; GST_ERROR_OBJECT (dec, "Input caps do not have a rate value"); } if (!gst_structure_get_int (structure, "channels", &channels)) { err = TRUE; GST_ERROR_OBJECT (dec, "Input caps do not have a channel value"); } if (err) return FALSE; } /* Get the caps that are allowed by downstream */ { GstCaps *allowed_srccaps_unnorm = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec)); allowed_srccaps = gst_caps_normalize (allowed_srccaps_unnorm); } /* Go through all allowed caps, pick the first one that matches */ for (structure_nr = 0; structure_nr < gst_caps_get_size (allowed_srccaps); ++structure_nr) { GstStructure *structure; gchar const *format_str; GstAudioFormat format; int encoding; structure = gst_caps_get_structure (allowed_srccaps, structure_nr); format_str = gst_structure_get_string (structure, "format"); if (format_str == NULL) { GST_DEBUG_OBJECT (dec, "Could not get format from src caps"); continue; } format = gst_audio_format_from_string (format_str); if (format == GST_AUDIO_FORMAT_UNKNOWN) { GST_DEBUG_OBJECT (dec, "Unknown format %s", format_str); continue; } switch (format) { case GST_AUDIO_FORMAT_S16: encoding = MPG123_ENC_SIGNED_16; break; case GST_AUDIO_FORMAT_S24: encoding = MPG123_ENC_SIGNED_24; break; case GST_AUDIO_FORMAT_S32: encoding = MPG123_ENC_SIGNED_32; break; case GST_AUDIO_FORMAT_U16: encoding = MPG123_ENC_UNSIGNED_16; break; case GST_AUDIO_FORMAT_U24: encoding = MPG123_ENC_UNSIGNED_24; break; case GST_AUDIO_FORMAT_U32: encoding = MPG123_ENC_UNSIGNED_32; break; case GST_AUDIO_FORMAT_F32: encoding = MPG123_ENC_FLOAT_32; break; default: GST_DEBUG_OBJECT (dec, "Format %s in srccaps is not supported", format_str); continue; } { int err; /* Cleanup old formats & set new one */ mpg123_format_none (mpg123_decoder->handle); err = mpg123_format (mpg123_decoder->handle, rate, channels, encoding); if (err != MPG123_OK) { GST_DEBUG_OBJECT (dec, "mpg123 cannot use caps %" GST_PTR_FORMAT " because mpg123_format() failed: %s", structure, mpg123_strerror (mpg123_decoder->handle)); continue; } } gst_audio_info_init (&(mpg123_decoder->next_audioinfo)); gst_audio_info_set_format (&(mpg123_decoder->next_audioinfo), format, rate, channels, NULL); GST_LOG_OBJECT (dec, "The next audio format is: %s, %u Hz, %u channels", format_str, rate, channels); mpg123_decoder->has_next_audioinfo = TRUE; match_found = TRUE; break; } gst_caps_unref (allowed_srccaps); return match_found; }
int main(int argc, char *argv[]) { SNDFILE* sndfile = NULL; SF_INFO sfinfo; mpg123_handle *mh = NULL; unsigned char* buffer = NULL; size_t buffer_size = 0; size_t done = 0; int channels = 0, encoding = 0; long rate = 0; int err = MPG123_OK; off_t samples = 0; if (argc!=3) usage(); printf( "Input file: %s\n", argv[1]); printf( "Output file: %s\n", argv[2]); err = mpg123_init(); if( err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL /* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */ || mpg123_open(mh, argv[1]) != MPG123_OK /* Peek into track and get first output format. */ || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ) { fprintf( stderr, "Trouble with mpg123: %s\n", mh==NULL ? mpg123_plain_strerror(err) : mpg123_strerror(mh) ); cleanup(mh); return -1; } if(encoding != MPG123_ENC_SIGNED_16) { /* Signed 16 is the default output format anyways; it would actually by only different if we forced it. So this check is here just for this explanation. */ cleanup(mh); fprintf(stderr, "Bad encoding: 0x%x!\n", encoding); return -2; } /* Ensure that this output format will not change (it could, when we allow it). */ mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); /* Buffer could be almost any size here, mpg123_outblock() is just some recommendation. Important, especially for sndfile writing, is that the size is a multiple of sample size. */ buffer_size = mpg123_outblock( mh ); buffer = malloc( buffer_size ); bzero(&sfinfo, sizeof(sfinfo) ); sfinfo.samplerate = rate; sfinfo.channels = channels; sfinfo.format = SF_FORMAT_WAV|SF_FORMAT_PCM_16; printf("Creating 16bit WAV with %i channels and %liHz.\n", channels, rate); sndfile = sf_open(argv[2], SFM_WRITE, &sfinfo); if(sndfile == NULL){ fprintf(stderr, "Cannot open output file!\n"); cleanup(mh); return -2; } do { err = mpg123_read( mh, buffer, buffer_size, &done ); sf_write_short( sndfile, (short*)buffer, done/sizeof(short) ); samples += done/sizeof(short); /* We are not in feeder mode, so MPG123_OK, MPG123_ERR and MPG123_NEW_FORMAT are the only possibilities. We do not handle a new format, MPG123_DONE is the end... so abort on anything not MPG123_OK. */ } while (err==MPG123_OK); if(err != MPG123_DONE) fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n", err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) ); sf_close( sndfile ); samples /= channels; printf("%li samples written.\n", (long)samples); cleanup(mh); return 0; }
int mp3decode_reg(struct xlplayer *xlplayer) { static pthread_once_t once_control = PTHREAD_ONCE_INIT; struct mp3decode_vars *self; struct chapter *chapter; int fd, rv; long rate; int channels, encoding; int src_error; pthread_once(&once_control, decoder_library_init); if (!decoder_library_ok) { fprintf(stderr, "mp3decode_reg: decoder library is not ok\n"); goto rej; } if (!(self = xlplayer->dec_data = calloc(1, sizeof (struct mp3decode_vars)))) { fprintf(stderr, "mp3decode_reg: malloc failure\n"); goto rej; } if (!(self->mh = mpg123_new(NULL, NULL))) { fprintf(stderr, "mp3decode_reg: handle not okay"); goto rej_; } #ifdef MPG123_AUTO_RESAMPLE if (mpg123_param(self->mh, MPG123_REMOVE_FLAGS, MPG123_AUTO_RESAMPLE, 0.0) != MPG123_OK) { fprintf(stderr, "mpgdecode_reg: failed to turn off auto resampling\n"); goto rej_; } #endif if (mpg123_param(self->mh, MPG123_ADD_FLAGS, MPG123_FORCE_STEREO, 0.0) != MPG123_OK) { fprintf(stderr, "mpgdecode_reg: failed to set flags"); goto rej_; } if (mpg123_format_none(self->mh) != MPG123_OK) { fprintf(stderr, "mp3decode_reg: failed to clear output formats"); goto rej_; } /* all the permitted mp3 sample rates are enabled * forced stereo is in effect so no need to add mono formats */ mpg123_format(self->mh, 48000, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 44100, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 32000, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 24000, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 22050, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 16000, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 12000, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 11025, MPG123_STEREO, MPG123_ENC_FLOAT_32); mpg123_format(self->mh, 8000, MPG123_STEREO, MPG123_ENC_FLOAT_32); if (!(self->fp = fopen(xlplayer->pathname, "r"))) { fprintf(stderr, "mp3decode_reg: failed to open %s\n", xlplayer->pathname); goto rej_; } mp3_tag_read(&self->taginfo, self->fp); lseek(fd = fileno(self->fp), 0, SEEK_SET); if ((rv = mpg123_open_fd(self->mh, fd)) != MPG123_OK) { fprintf(stderr, "mp3decode_reg: mpg123_open_fd failed with return value %d\n", rv); goto rej__; } if (mpg123_getformat(self->mh, &rate, &channels, &encoding) != MPG123_OK || channels != 2) { fprintf(stderr, "mp3decode_reg: mpg123_getformat returned unexpected value\n"); goto rej___; } if (rate != xlplayer->samplerate) { fprintf(stderr, "mp3decode_reg: configuring resampler\n"); xlplayer->src_state = src_new(xlplayer->rsqual, channels, &src_error); if (src_error) { fprintf(stderr, "mp3decode_reg: src_new reports %s\n", src_strerror(src_error)); goto rej___; } xlplayer->src_data.src_ratio = (double)xlplayer->samplerate / (double)rate; xlplayer->src_data.end_of_input = 0; size_t output_frames = (size_t)(xlplayer->src_data.src_ratio * 1.1 * 1152); xlplayer->src_data.output_frames = (long)output_frames; if (!(xlplayer->src_data.data_out = malloc(output_frames * 2 * sizeof (float)))) { fprintf(stderr, "mp3decode_reg: malloc failure\n"); goto rej____; } self->resample = TRUE; } xlplayer->dec_init = mp3decode_init; xlplayer->dec_play = mp3decode_play; xlplayer->dec_eject = mp3decode_eject; if ((chapter = mp3_tag_chapter_scan(&self->taginfo, xlplayer->play_progress_ms + 70))) { self->current_chapter = chapter; xlplayer_set_dynamic_metadata(xlplayer, dynamic_metadata_form[chapter->title.encoding], chapter->artist.text, chapter->title.text, chapter->album.text, 0); } if (xlplayer->seek_s) if (mpg123_seek(self->mh, (off_t)rate * xlplayer->seek_s, SEEK_SET) < 0) { fprintf(stderr, "mp3decode_init: seek failed\n"); mp3decode_eject(xlplayer); xlplayer->playmode = PM_STOPPED; xlplayer->command = CMD_COMPLETE; } return ACCEPTED; rej____: xlplayer->src_state = src_delete(xlplayer->src_state); rej___: mpg123_delete(self->mh); rej__: mp3_tag_cleanup(&self->taginfo); fclose(self->fp); rej_: free(self); rej: return REJECTED; }
int main(int argc, char *argv[]) { SNDFILE* sndfile = NULL; SF_INFO sfinfo; mpg123_handle *mh = NULL; unsigned char* buffer = NULL; size_t buffer_size = 0; size_t done = 0; int channels = 0, encoding = 0; long rate = 0; int err = MPG123_OK; off_t samples = 0; if (argc<3) usage(); printf( "Input file: %s\n", argv[1]); printf( "Output file: %s\n", argv[2]); err = mpg123_init(); if(err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL) { fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err)); cleanup(mh); return -1; } /* Simple hack to enable floating point output. */ if(argc >= 4 && !strcmp(argv[3], "f32")) mpg123_param(mh, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT, 0.); /* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */ if( mpg123_open(mh, argv[1]) != MPG123_OK /* Peek into track and get first output format. */ || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ) { fprintf( stderr, "Trouble with mpg123: %s\n", mpg123_strerror(mh) ); cleanup(mh); return -1; } if(encoding != MPG123_ENC_SIGNED_16 && encoding != MPG123_ENC_FLOAT_32) { /* Signed 16 is the default output format anyways; it would actually by only different if we forced it. So this check is here just for this explanation. */ cleanup(mh); fprintf(stderr, "Bad encoding: 0x%x!\n", encoding); return -2; } /* Ensure that this output format will not change (it could, when we allow it). */ mpg123_format_none(mh); mpg123_format(mh, rate, channels, encoding); bzero(&sfinfo, sizeof(sfinfo) ); sfinfo.samplerate = rate; sfinfo.channels = channels; sfinfo.format = SF_FORMAT_WAV|(encoding == MPG123_ENC_SIGNED_16 ? SF_FORMAT_PCM_16 : SF_FORMAT_FLOAT); printf("Creating WAV with %i channels and %liHz.\n", channels, rate); sndfile = sf_open(argv[2], SFM_WRITE, &sfinfo); if(sndfile == NULL){ fprintf(stderr, "Cannot open output file!\n"); cleanup(mh); return -2; } /* Buffer could be almost any size here, mpg123_outblock() is just some recommendation. Important, especially for sndfile writing, is that the size is a multiple of sample size. */ buffer_size = argc >= 5 ? atol(argv[4]) : mpg123_outblock(mh); buffer = malloc( buffer_size ); do { sf_count_t more_samples; err = mpg123_read( mh, buffer, buffer_size, &done ); more_samples = encoding == MPG123_ENC_SIGNED_16 ? sf_write_short(sndfile, (short*)buffer, done/sizeof(short)) : sf_write_float(sndfile, (float*)buffer, done/sizeof(float)); if(more_samples < 0 || more_samples*mpg123_encsize(encoding) != done) { fprintf(stderr, "Warning: Written number of samples does not match the byte count we got from libmpg123: %li != %li\n", (long)(more_samples*mpg123_encsize(encoding)), (long)done); } samples += more_samples; /* We are not in feeder mode, so MPG123_OK, MPG123_ERR and MPG123_NEW_FORMAT are the only possibilities. We do not handle a new format, MPG123_DONE is the end... so abort on anything not MPG123_OK. */ } while (err==MPG123_OK); if(err != MPG123_DONE) fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n", err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) ); sf_close( sndfile ); samples /= channels; printf("%li samples written.\n", (long)samples); cleanup(mh); return 0; }