/** Decodes given buffer of data to PCM */ jint Java_com_denisigo_netradioplayer_Decoder_decodeNative(JNIEnv* env, jobject thiz, jint handle, jbyteArray in_buffer, jint size, jbyteArray out_buffer, jint max_size){ jint ret; mpg123_handle* hnd = (mpg123_handle*) handle; jbyte* in_buf = (*env)->GetByteArrayElements(env, in_buffer, NULL); jbyte* out_buf = (*env)->GetByteArrayElements(env, out_buffer, NULL); size_t bytes_decoded; // Decode data ret = mpg123_decode(hnd, in_buf, size, out_buf, max_size, &bytes_decoded); LOG("Decoded %d bytes, ret: %d, max_size: %d", bytes_decoded, ret, max_size); // If status if OK, decoder decoded something if (ret == MPG123_OK){ ret = bytes_decoded; } // This means decoder faced new stream. For us this means that there was sufficient data decoded // to determine stream's params and we can notify Java Decoder about it else if (ret == MPG123_NEW_FORMAT){ long rate; int channels, encoding; // Get actual format params mpg123_getformat(hnd, &rate, &channels, &encoding); //LOG("mpg123_getformat: rate: %d channels: %d encoding: %d\n", rate, channels, encoding); // We support only 16 and 8 bits per sample if (encoding == MPG123_ENC_SIGNED_16) encoding = 16; else if (encoding == MPG123_ENC_SIGNED_8) encoding = 8; else encoding = -1; (*env)->CallVoidMethod(env, thiz, method_onNewFormatCallback, (jint)rate, (jint)channels, (jint)encoding); ret = 0; } // This means mpg123 decoder needs more data to provide decoded data else if (ret == MPG123_NEED_MORE){ ret = 0; } // Other cases usually means some errors else { // Ensure we will not return positive number which is normally indicating num of decoded bytes if (ret > 0) ret *= -1; } (*env)->ReleaseByteArrayElements(env, in_buffer, in_buf, 0); (*env)->ReleaseByteArrayElements(env, out_buffer, out_buf, 0); return ret; }
/* decode anything mpg123 can */ void decode_mpeg(VGMSTREAMCHANNEL *stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels) { int samples_done = 0; while (samples_done < samples_to_do) { size_t bytes_done; int rc; if (!data->buffer_full) { data->bytes_in_buffer = read_streamfile(data->buffer, stream->offset,MPEG_BUFFER_SIZE,stream->streamfile); data->buffer_full = 1; data->buffer_used = 0; stream->offset += data->bytes_in_buffer; } if (!data->buffer_used) { rc = mpg123_decode(data->m, data->buffer,data->bytes_in_buffer, (unsigned char *)(outbuf+samples_done*channels), (samples_to_do-samples_done)*sizeof(sample)*channels, &bytes_done); data->buffer_used = 1; } else { rc = mpg123_decode(data->m, NULL,0, (unsigned char *)(outbuf+samples_done*channels), (samples_to_do-samples_done)*sizeof(sample)*channels, &bytes_done); } if (rc == MPG123_NEED_MORE) data->buffer_full = 0; samples_done += bytes_done/sizeof(sample)/channels; } }
QString InternetFormatSupport( const char* address ) { loadCURL(); if ( !CURLloaded ) return ""; mpg123_handle *mus = mpg123_new(NULL, NULL); mpg123_open_feed( mus ); URL_FILE *f = url_fopen( address ); if ( !f ) { unloadCURL(); return ""; } char *data; int _DATA_BUFF; if ( !getDataBuff( f, url_fread, _DATA_BUFF, &data ) ) { url_fclose(f); unloadCURL(); return ""; } int bread = url_fread(data+10, 1, _DATA_BUFF-10, f); mpg123_decode( mus, (const unsigned char*)data, bread, 0,0,0 ); bool loaded = getMusInfo( mus, 0,0,0,0,0, -1, "" ); mpg123_close(mus); mpg123_delete(mus); delete[] data; url_fclose(f); unloadCURL(); if ( loaded ) return plugName; else return ""; }
bool Reader::readSamples(int** dest, int destChannels, int destOffset, int64 startSampleInFile, int numSamples) { std::cout << "start sample in file: " << startSampleInFile << std::endl; unsigned char tmp_buf[numSamples]; int r = AudioFormatReader::input->read(tmp_buf, numSamples); std::cout << "read " << r << " on " << numSamples << ", pos: " << AudioFormatReader::input->getPosition() << ", remaining: " << AudioFormatReader::input->getNumBytesRemaining() << ", exhausted: " << AudioFormatReader::input->isExhausted() << std::endl; if (mpg123_seek(mh_, startSampleInFile, SEEK_SET) < 0) { std::cout << "couldn't seek -- returning" << std::endl; return false; } int64 bytesPerSample = this->bitsPerSample / 8; size_ = numSamples * numChannels * bytesPerSample; if (allocated_ < size_) { if (buffer_) free(buffer_); buffer_ = malloc(size_); allocated_ = size_; } size_t bytesCopied; Error e = mpg123_read(mh_, (uchar*) buffer_, size_, &bytesCopied); if (e != MPG123_DONE && e != MPG123_OK) return false; int64 sourceSize = bytesCopied / (bytesPerSample * numChannels); copier_(dest, destChannels, destOffset, buffer_, numChannels, sourceSize); return (bytesCopied == size_); #if 0 if (AudioFormatReader::input->getTotalLength()<0) { // infinite stream std::cout << " INFINITE STREAM" << std::endl; if (mpg123_seek(mh_, startSampleInFile, SEEK_SET) < 0) { std::cout << "couldn't seek in data!" << std::endl; return false; } InputStream *in = AudioFormatReader::input; int64 bytesPerSample = this->bitsPerSample / 8; size_ = numSamples * numChannels * bytesPerSample; unsigned char buf[numSamples], out[size_]; size_t writtenBytes; size_t bytesCopied = 0; int ret; mpg123_param(mh_, MPG123_VERBOSE, 2, 0); while(ret!=MPG123_ERR && ret!=MPG123_NEED_MORE) { std::cout << "looping..." << std::endl; int len = in->read(buf, numSamples); if(len<=0) { std::cout << "no more data to read!..." << std::endl; return false; } ret = mpg123_decode(mh_, buf, len, out, size_, &writtenBytes); bytesCopied+=writtenBytes; if(ret==MPG123_OK) { std::cout << "OK!" << std::endl; break; } else { std::cout << "returned: " << mpg123_strerror(mh_) << std::endl; } } for (int i=0;i<10;++i) { std::cout << "out " << i << " -> " << (int)out[i] << std::endl; } int64 sourceSize = bytesCopied / (bytesPerSample * numChannels); copier_(dest, destChannels, destOffset, out, numChannels, sourceSize); std::cout << "infinite bytesCopied: " << bytesCopied << ", size_: " << size_ << ", startSampleInFile: " << startSampleInFile << std::endl; return (bytesCopied == size_); /* unsigned char buf[numSamples]; int len, num; unsigned char *audio; Error ret, state; size_t bytes; off_t inoffset; while((ret = mpg123_feedseek(mh_, numSamples, SEEK_SET, &inoffset)) == MPG123_NEED_MORE) { std::cout << "need more..." << std::endl; int len = AudioFormatReader::input->read(buf, numSamples); if(len <= 0) break; state = mpg123_feed(mh_, buf, len); if(state == MPG123_ERR) { std::cout << "Error: " << mpg123_strerror(mh_) << std::endl; return -1; } } if(ret == MPG123_ERR) { std::cout << "Feedseek failed: " << mpg123_strerror(mh_) << std::endl; return false; } else { std::cout << "well, feedseek succeeded ???? " << inoffset << ", " << mpg123_strerror(mh_) << std::endl; } AudioFormatReader::input->setPosition(inoffset); len = AudioFormatReader::input->read(buf, numSamples); if(len <= 0) { std::cout << "no data read from stream" << std::endl; return false; } ret = mpg123_feed(mh_, buf, len); if(ret == MPG123_ERR) { std::cout << "feed failed: " << mpg123_strerror(mh_) << std::endl; return false; } */ } else { if (mpg123_seek(mh_, startSampleInFile, SEEK_SET) < 0) return false; } int64 bytesPerSample = this->bitsPerSample / 8; size_ = numSamples * numChannels * bytesPerSample; if (allocated_ < size_) { if (buffer_) free(buffer_); buffer_ = malloc(size_); allocated_ = size_; } size_t bytesCopied; Error e = mpg123_read(mh_, (uchar*) buffer_, size_, &bytesCopied); if (e != MPG123_DONE && e != MPG123_OK) { std::cout << "can't read data: " << mpg123_strerror(mh_) << std::endl; return false; } int64 sourceSize = bytesCopied / (bytesPerSample * numChannels); copier_(dest, destChannels, destOffset, buffer_, numChannels, sourceSize); std::cout << "bytesCopied: " << bytesCopied << ", size_: " << size_ << ", startSampleInFile: " << startSampleInFile << std::endl; return (bytesCopied == size_); #endif }
void play( const char *fileE, int ) { if ( Type != 0 && Type != 2 ) return ERROR2( "Wtyczka obsługuje tylko odczyt plików i strumienia internetowego!" ); if ( Type == 2 ) { QString tmp = loadCURL(); if ( !CURLloaded ) return ERROR2( "Nie można załadować biblioteki: "+QMPInternetf+libExt+"\n"+tmp ); } if ( fileE != curF ) clrPos(); clrSet(); QString BLAD; if ( Type == 0 ) BLAD = "Błąd odczytu pliku!"; else if ( Type == 2 ) BLAD = "Nie można otworzyć strumienia internetowego!"; musicfile = mpg123_new(NULL, NULL); if ( Type == 0 ) { fd = qmp_open( fileE, O_RDONLY|O_BINARY ); mpg123_open_fd( musicfile, fd ); } if ( Type == 2 ) { title = "Czekaj, trwa otwieranie..."; mpg123_open_feed( musicfile ); f = url_fopen(fileE,0,1); if ( !f ) return ERROR(BLAD); if ( !getDataBuff( f, url_fread, _DATA_BUFF, &data, &bolStop ) ) return ERROR(BLAD); url_fread(data+10, 1, _DATA_BUFF-10, f); if ( getNetInfo( f, FILE_SIZE ) > 0.0 ) knownSize = true; mpg123_decode( musicfile, (const unsigned char*)data, _DATA_BUFF, 0,0,0 ); } if ( !musicfile ) return ERROR(BLAD); curF = fileE; if ( !MP3Update() ) return ERROR(BLAD); if ( Type == 2 && title.isEmpty() ) title = fileE; if ( Type == 2 || ( Type == 0 && fileE[0] == '/' && fileE[1] == '/' ) ) QOut->useQMPBuffer(); QOut->Init( AudioInfo( rate, 16, chn ), true, 0, fileE, /*title*/Title ); if ( *QOut->PlErr ) { *QOut->PlErr = false; return ERROR("Błąd zwraca wtyczka wyjściowa!"); } IsPlaying = true; size_t bDecoded = 0; audio_buffer = new char[BUF_SIZE]; TMPint = 0; int musErr = 0; for(;;) { if ( bolStop ) break; if ( !IsPaused ) { if ( !*QOut->mustReset ) { if ( doSeek ) { mpg123_seek( musicfile, doSeek, SEEK_SET ); QOut->control( QOUT_NEXT_READ ); doSeek = 0; } musErr = mpg123_read( musicfile, (unsigned char*)audio_buffer, BUF_SIZE, &bDecoded ); if ( musErr == MPG123_DONE ) break; if ( musErr == MPG123_ERR && !searchParts ) break; QOut->Play( audio_buffer, bDecoded, pltime, false ); MP3Update2( bDecoded ); if ( musErr == MPG123_NEED_MORE && Type != 0 ) { int bread = url_fread( data, 1, _DATA_BUFF, f ); if ( ( !bread && !wait4Data ) || ( !bread && url_feof(f) ) ) break; else if ( !bread ) MYsleep( 25 ); mpg123_decode( musicfile, (const unsigned char*)data, bread, NULL, 0, NULL ); } } else QOut->Play(0,0,pltime,true); } else QOut->Play(0,0,pltime,true); } STOP(); }
static int MP3_open(FILE* fp, struct amci_file_desc_t* fmt_desc, int options, long h_codec) { #ifdef WITH_MPG123DECODER unsigned char mp_rd_buf[20]; size_t sr, decoded_size; mp3_coder_state* coder_state; int res; DBG("mp3_open.\n"); #endif if(options == AMCI_RDONLY){ #ifndef WITH_MPG123DECODER ERROR("MP3 decoding support not compiled in.\n"); return -1; #else if (!h_codec) { ERROR("mp3 decoder not initialized!\n"); return -1; } coder_state = (mp3_coder_state*)h_codec; DBG("Initializing mpg123 codec state.\n"); res = mpg123_open_feed(coder_state->mpg123_h); if (MPG123_ERR == res) { ERROR("mpg123_open_feed returned mpg123 error '%s'\n", mpg123_strerror(coder_state->mpg123_h)); return -1; } /* read until we know the format */ while (res!= MPG123_NEW_FORMAT) { SAFE_READ(mp_rd_buf, 20, fp, sr); res = mpg123_decode(coder_state->mpg123_h, mp_rd_buf, 20, mp_rd_buf, 0, &decoded_size); if (res == MPG123_ERR) { ERROR("trying to determine MP3 file format: '%s'\n", mpg123_strerror(coder_state->mpg123_h)); return -1; } } mpg123_getformat(coder_state->mpg123_h, &coder_state->rate, &coder_state->channels, &coder_state->enc); DBG("mpg123: New format: %li Hz, %i channels, encoding value %i\n", coder_state->rate, coder_state->channels, coder_state->enc); fmt_desc->subtype = 1; // ? fmt_desc->rate = coder_state->rate; fmt_desc->channels = coder_state->channels; fmt_desc->data_size = -1; /* set buffering parameters */ fmt_desc->buffer_size = MP3_FRAMESAMPLES * 8; fmt_desc->buffer_thresh = MP3_FRAMESAMPLES; fmt_desc->buffer_full_thresh = MP3_FRAMESAMPLES * 3; return 0; #endif } return 0; }
/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they * actually vary and are much shorter */ void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do) { int samples_done = 0; while (samples_done < samples_to_do) { size_t bytes_done; int rc; if (!data->buffer_full) { /* fill buffer up to next frame ending (or file ending) */ int bytes_into_header = 0; const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0}; off_t frame_offset = 0; /* assume that we are starting at a header, skip it and look for the * next one */ read_streamfile(data->buffer, stream->offset+frame_offset, 4, stream->streamfile); frame_offset += 4; do { uint8_t byte; byte = read_8bit(stream->offset+frame_offset,stream->streamfile); data->buffer[frame_offset] = byte; frame_offset++; if (byte == header[bytes_into_header]) { bytes_into_header++; } else { /* This might have been the first byte of the header, so * we need to check again. * No need to get more complicated than this, though, since * there are no repeated characters in the search string. */ if (bytes_into_header>0) { frame_offset--; } bytes_into_header=0; } if (bytes_into_header==4) { break; } } while (frame_offset < AHX_EXPECTED_FRAME_SIZE); if (bytes_into_header==4) frame_offset-=4; memset(data->buffer+frame_offset,0, AHX_EXPECTED_FRAME_SIZE-frame_offset); data->buffer_full = 1; data->buffer_used = 0; stream->offset += frame_offset; } if (!data->buffer_used) { rc = mpg123_decode(data->m, data->buffer,AHX_EXPECTED_FRAME_SIZE, (unsigned char *)(outbuf+samples_done), (samples_to_do-samples_done)*sizeof(sample), &bytes_done); data->buffer_used = 1; } else { rc = mpg123_decode(data->m, NULL,0, (unsigned char *)(outbuf+samples_done), (samples_to_do-samples_done)*sizeof(sample), &bytes_done); } if (rc == MPG123_NEED_MORE) data->buffer_full = 0; samples_done += bytes_done/sizeof(sample); } }
/* This tries to extract a requested amount of decoded data. * Even when you request 0 bytes, it will feed enough input so that * the decoder _could_ have delivered something. * Returns byte count >= 0, -1 on error. * * Thoughts on exact pts keeping: * We have to assume that MPEG frames are cut in pieces by packet boundaries. * Also, it might be possible that the first packet does not contain enough * data to ensure initial stream sync... or re-sync on erroneous streams. * So we need something robust to relate the decoded byte count to the correct * time stamp. This is tricky, though. From the outside, you cannot tell if, * after having fed two packets until the first output arrives, one should * start counting from the first packet's pts or the second packet's. * So, let's just count from the last fed package's pts. If the packets are * exactly cut to MPEG frames, this will cause one frame mismatch in the * beginning (when mpg123 peeks ahead for the following header), but will * be corrected with the third frame already. One might add special code to * not increment the base pts past the first packet's after a resync before * the first decoded bytes arrived. */ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) { int ret = MPG123_OK; int got = 0; struct ad_mpg123_context *con = sh->context; /* There will be one MPG123_NEW_FORMAT message on first open. * This will be handled in init(). */ do { size_t got_now = 0; /* Feed the decoder. This will only fire from the second round on. */ if (ret == MPG123_NEED_MORE) { int incount; double pts; unsigned char *inbuf; /* Feed more input data. */ incount = ds_get_packet_pts(sh->ds, &inbuf, &pts); if (incount <= 0) break; /* Apparently that's it. EOF. */ /* Next bytes from that presentation time. */ if (pts != MP_NOPTS_VALUE) { sh->pts = pts; sh->pts_bytes = 0; } #ifdef AD_MPG123_FRAMEWISE /* Have to use mpg123_feed() to avoid decoding here. */ ret = mpg123_feed(con->handle, inbuf, incount); #else /* Do not use mpg123_feed(), added in later libmpg123 versions. */ ret = mpg123_decode(con->handle, inbuf, incount, NULL, 0, NULL); #endif if (ret == MPG123_ERR) break; } /* Theoretically, mpg123 could return MPG123_DONE, so be prepared. * Should not happen in our usage, but it is a valid return code. */ else if (ret == MPG123_ERR || ret == MPG123_DONE) break; /* Try to decode a bit. This is the return value that counts * for the loop condition. */ #ifdef AD_MPG123_FRAMEWISE if (!buf) { /* fake call just for feeding to get format */ ret = mpg123_getformat(con->handle, NULL, NULL, NULL); } else { /* This is the decoding. One frame at a time. */ ret = mpg123_replace_buffer(con->handle, buf, count); if (ret == MPG123_OK) ret = mpg123_decode_frame(con->handle, NULL, NULL, &got_now); } #else ret = mpg123_decode(con->handle, NULL, 0, buf + got, count - got, &got_now); #endif got += got_now; sh->pts_bytes += got_now; #ifdef AD_MPG123_FRAMEWISE } while (ret == MPG123_NEED_MORE || (got == 0 && count != 0)); #else } while (ret == MPG123_NEED_MORE || got < count);
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; int32_t channel_count; int32_t interleave; int32_t sample_rate; int32_t loop_start; int32_t loop_end; int32_t start_offset; int32_t header_size; int32_t coef[2]; int32_t dsp_interleave_type; char filename[260]; int coding; #ifdef VGM_USE_MPEG mpeg_codec_data *data = NULL; #endif /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("genh",filename_extension(filename))) goto fail; /* check header magic */ if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail; /* check channel count (needed for ADP/DTK check) */ channel_count = read_32bitLE(0x4,streamFile); if (channel_count < 1) goto fail; /* check format */ /* 0 = PSX ADPCM */ /* 1 = XBOX IMA ADPCM */ /* 2 = NGC ADP/DTK ADPCM */ /* 3 = 16bit big endian PCM */ /* 4 = 16bit little endian PCM */ /* 5 = 8bit PCM */ /* 6 = SDX2 */ /* 7 = DVI IMA */ /* 8 = MPEG-1 Layer III, possibly also the MPEG-2 and 2.5 extensions */ /* 9 = IMA */ /* 10 = AICA ADPCM */ /* 11 = MS ADPCM */ /* 12 = NGC DSP */ /* 13 = 8bit unsingned PCM */ /* 14 = PSX ADPCM (bad flagged) */ /* ... others to come */ switch (read_32bitLE(0x18,streamFile)) { case 0: coding = coding_PSX; break; case 1: coding = coding_XBOX; break; case 2: coding = coding_NGC_DTK; if (channel_count != 2) goto fail; break; case 3: coding = coding_PCM16BE; break; case 4: coding = coding_PCM16LE; break; case 5: coding = coding_PCM8; break; case 6: coding = coding_SDX2; break; case 7: coding = coding_DVI_IMA; break; #ifdef VGM_USE_MPEG case 8: /* we say MPEG-1 L3 here, but later find out exactly which */ coding = coding_MPEG1_L3; break; #endif case 9: coding = coding_IMA; break; case 10: coding = coding_AICA; break; case 11: coding = coding_MSADPCM; break; case 12: coding = coding_NGC_DSP; break; case 13: coding = coding_PCM8_U_int; break; case 14: coding = coding_PSX_badflags; break; default: goto fail; } start_offset = read_32bitLE(0x1C,streamFile); header_size = read_32bitLE(0x20,streamFile); /* HACK to support old genh */ if (header_size == 0) { start_offset = 0x800; header_size = 0x800; } /* check for audio data start past header end */ if (header_size > start_offset) goto fail; interleave = read_32bitLE(0x8,streamFile); sample_rate = read_32bitLE(0xc,streamFile); loop_start = read_32bitLE(0x10,streamFile); loop_end = read_32bitLE(0x14,streamFile); coef[0] = read_32bitLE(0x24,streamFile); coef[1] = read_32bitLE(0x28,streamFile); dsp_interleave_type = read_32bitLE(0x2C,streamFile); //if (coding == coding_XBOX && channel_count != 2) goto fail; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,(loop_start!=-1)); if (!vgmstream) goto fail; /* fill in the vital information */ vgmstream->channels = channel_count; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = loop_end; vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; vgmstream->loop_flag = (loop_start != -1); switch (coding) { case coding_PCM8_U_int: vgmstream->layout_type=layout_none; break; case coding_PCM16LE: case coding_PCM16BE: case coding_PCM8: case coding_SDX2: case coding_PSX: case coding_PSX_badflags: case coding_DVI_IMA: case coding_IMA: case coding_AICA: vgmstream->interleave_block_size = interleave; if (channel_count > 1) { if (coding == coding_SDX2) { coding = coding_SDX2_int; vgmstream->coding_type = coding_SDX2_int; } if(vgmstream->interleave_block_size==0xffffffff) vgmstream->layout_type=layout_none; else { vgmstream->layout_type = layout_interleave; if(coding==coding_DVI_IMA) coding=coding_INT_DVI_IMA; if(coding==coding_IMA) coding=coding_INT_IMA; } } else { vgmstream->layout_type = layout_none; } break; case coding_MSADPCM: if (channel_count != 2) goto fail; vgmstream->interleave_block_size = interleave; vgmstream->layout_type = layout_none; break; case coding_XBOX: vgmstream->layout_type = layout_none; break; case coding_NGC_DTK: vgmstream->layout_type = layout_dtk_interleave; break; case coding_NGC_DSP: if (dsp_interleave_type == 0) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = interleave; } else if (dsp_interleave_type == 1) { vgmstream->layout_type = layout_interleave_byte; vgmstream->interleave_block_size = interleave; } else if (dsp_interleave_type == 2) { vgmstream->layout_type = layout_none; } break; #ifdef VGM_USE_MPEG case coding_MPEG1_L3: vgmstream->layout_type = layout_mpeg; break; #endif } vgmstream->coding_type = coding; vgmstream->meta_type = meta_GENH; /* open the file for reading by each channel */ { int i; int j; STREAMFILE * chstreamfile = NULL; for (i=0;i<channel_count;i++) { off_t chstart_offset = start_offset; switch (coding) { case coding_PSX: case coding_PSX_badflags: case coding_PCM16BE: case coding_PCM16LE: case coding_SDX2: case coding_SDX2_int: case coding_DVI_IMA: case coding_IMA: case coding_PCM8: case coding_PCM8_U_int: case coding_AICA: case coding_INT_DVI_IMA: case coding_INT_IMA: if (vgmstream->layout_type == layout_interleave) { if (interleave >= 512) { chstreamfile = streamFile->open(streamFile,filename,interleave); } else { if (!chstreamfile) chstreamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); } chstart_offset = start_offset+vgmstream->interleave_block_size*i; } else { chstreamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); } break; case coding_XBOX: case coding_MSADPCM: /* xbox's "interleave" is a lie, all channels start at same * offset */ chstreamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); break; case coding_NGC_DTK: if (!chstreamfile) chstreamfile = streamFile->open(streamFile,filename,32*0x400); break; case coding_NGC_DSP: if (!chstreamfile) chstreamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); for (j=0;j<16;j++) vgmstream->ch[i].adpcm_coef[j] = read_16bitBE(coef[i]+j*2,streamFile); chstart_offset =start_offset+vgmstream->interleave_block_size*i; break; #ifdef VGM_USE_MPEG case coding_MPEG1_L3: if (!chstreamfile) chstreamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); break; #endif } if (!chstreamfile) goto fail; vgmstream->ch[i].streamfile = chstreamfile; vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=chstart_offset; } } #ifdef VGM_USE_MPEG if (coding == coding_MPEG1_L3) { int rc; off_t read_offset; data = calloc(1,sizeof(mpeg_codec_data)); if (!data) goto mpeg_fail; data->m = mpg123_new(NULL,&rc); if (rc==MPG123_NOT_INITIALIZED) { if (mpg123_init()!=MPG123_OK) goto mpeg_fail; data->m = mpg123_new(NULL,&rc); if (rc!=MPG123_OK) goto mpeg_fail; } else if (rc!=MPG123_OK) { goto mpeg_fail; } mpg123_param(data->m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0); if (mpg123_open_feed(data->m)!=MPG123_OK) { goto mpeg_fail; } /* check format */ read_offset=0; do { size_t bytes_done; if (read_streamfile(data->buffer, start_offset+read_offset, MPEG_BUFFER_SIZE,vgmstream->ch[0].streamfile) != MPEG_BUFFER_SIZE) goto mpeg_fail; read_offset+=1; rc = mpg123_decode(data->m,data->buffer,MPEG_BUFFER_SIZE, NULL,0,&bytes_done); if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT && rc != MPG123_NEED_MORE) goto mpeg_fail; } while (rc != MPG123_NEW_FORMAT); { long rate; int channels,encoding; struct mpg123_frameinfo mi; rc = mpg123_getformat(data->m,&rate,&channels,&encoding); if (rc != MPG123_OK) goto mpeg_fail; if (rate != vgmstream->sample_rate || channels != vgmstream->channels || encoding != MPG123_ENC_SIGNED_16) goto mpeg_fail; mpg123_info(data->m,&mi); if (mi.rate != vgmstream->sample_rate) goto mpeg_fail; if (mi.version == MPG123_1_0 && mi.layer == 1) vgmstream->coding_type = coding_MPEG1_L1; else if (mi.version == MPG123_1_0 && mi.layer == 2) vgmstream->coding_type = coding_MPEG1_L2; else if (mi.version == MPG123_1_0 && mi.layer == 3) vgmstream->coding_type = coding_MPEG1_L3; else if (mi.version == MPG123_2_0 && mi.layer == 1) vgmstream->coding_type = coding_MPEG2_L1; else if (mi.version == MPG123_2_0 && mi.layer == 2) vgmstream->coding_type = coding_MPEG2_L2; else if (mi.version == MPG123_2_0 && mi.layer == 3) vgmstream->coding_type = coding_MPEG2_L3; else if (mi.version == MPG123_2_5 && mi.layer == 1) vgmstream->coding_type = coding_MPEG25_L1; else if (mi.version == MPG123_2_5 && mi.layer == 2) vgmstream->coding_type = coding_MPEG25_L2; else if (mi.version == MPG123_2_5 && mi.layer == 3) vgmstream->coding_type = coding_MPEG25_L3; else goto mpeg_fail; } /* reinit, to ignore the reading we've done so far */ mpg123_open_feed(data->m); vgmstream->codec_data = data; } #endif return vgmstream; /* clean up anything we may have opened */ #ifdef VGM_USE_MPEG mpeg_fail: if (data) { mpg123_delete(data->m); free(data); } #endif fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
bool nuiAudioDecoder::ReadInfo() { if (!mpPrivate) { return false; } int err; int read; int toread = DECODER_INPUT_SIZE; unsigned char* pInput = new unsigned char[toread]; do { read = mrStream.ReadUInt8(pInput, toread); size_t done = 0; err = mpg123_decode(mpPrivate->mpHandle, pInput, read, NULL, 0, &done); // err = mpg123_feed(mpPrivate->mpHandle, pInput, read); } while (err != MPG123_NEW_FORMAT && read > 0); mpg123_frameinfo frameinfo; err = mpg123_info(mpPrivate->mpHandle, &frameinfo); if (err != MPG123_OK) { return false; } int channels; if (frameinfo.mode == MPG123_M_MONO) channels = 1; else channels = 2; double samplerate = 44100; int encoding = MPG123_ENC_SIGNED_16; int supportedChannelConfig = mpg123_format_support(mpPrivate->mpHandle, samplerate, encoding); if (supportedChannelConfig == 0) { return false; } int channelConfig; bool mono = (supportedChannelConfig & MPG123_MONO) && (channels == 1); bool stereo = (supportedChannelConfig & MPG123_STEREO) && (channels == 2); if (mono) channelConfig = MPG123_MONO; else if (stereo) channelConfig = MPG123_STEREO; else { return false; } mpg123_format_none(mpPrivate->mpHandle); err = mpg123_format(mpPrivate->mpHandle, samplerate, channelConfig, encoding); if (err != MPG123_OK) { return false; } off_t sampleframes = mpg123_length(mpPrivate->mpHandle); if (sampleframes <= 0) { int bitrate = frameinfo.bitrate; nglFileSize streamSize = mrStream.Available(); sampleframes = (streamSize / (bitrate * 1000.f / 8.f)) * samplerate; } int BitsPerSample; if (encoding == MPG123_ENC_FLOAT_32) BitsPerSample = 32; else if (encoding == MPG123_ENC_SIGNED_16) BitsPerSample = 16; else { return false; } mInfo.SetSampleFrames(sampleframes); mInfo.SetSampleRate(samplerate); mInfo.SetChannels(channels); mInfo.SetBitsPerSample(BitsPerSample); mInfo.SetFileFormat(eAudioCompressed); mInfo.SetStartFrame(0); mInfo.SetStopFrame(mInfo.GetSampleFrames()); return true; }
int mpa_decode_frm(struct audec_state *ads, int fmt, void *sampv_void, size_t *sampc, const uint8_t *buf, size_t len) { int result, channels, encoding, i; long samplerate; size_t n; spx_uint32_t intermediate_len; spx_uint32_t out_len; int16_t *sampv = sampv_void; #ifdef DEBUG debug("MPA dec start %d %ld\n",len, *sampc); #endif if (!ads || !sampv || !sampc || !buf || len<=4) return EINVAL; if (*(uint32_t*)(void *)buf != 0) { warning("MPA dec header is not zero %08X, not supported yet\n", *(uint32_t*)(void *)buf); return EPROTO; } if (fmt != AUFMT_S16LE) return ENOTSUP; n = 0; result = mpg123_decode(ads->dec, buf+4, len-4, (unsigned char*)ads->intermediate_buffer, sizeof(ads->intermediate_buffer), &n); /* n counts bytes */ #ifdef DEBUG debug("MPA dec %d %d %d %d\n",result, len-4, n, ads->channels); #endif if (result == MPG123_NEW_FORMAT) { mpg123_getformat(ads->dec, &samplerate, &channels, &encoding); info("MPA dec format change %d %d %04X\n",samplerate ,channels,encoding); ads->channels = channels; ads->start = 0; if (ads->resampler) speex_resampler_destroy(ads->resampler); if (samplerate != MPA_IORATE) { ads->resampler = speex_resampler_init(channels, (uint32_t)samplerate, MPA_IORATE, 3, &result); if (result!=RESAMPLER_ERR_SUCCESS || ads->resampler==NULL) { warning("MPA dec upsampler failed %d\n", result); return EINVAL; } } else ads->resampler = NULL; } else if (result == MPG123_NEED_MORE) ; /* workaround: do nothing */ else if (result != MPG123_OK) { warning("MPA dec feed error %d %s\n", result, mpg123_plain_strerror(result)); return EPROTO; } if (ads->resampler) { intermediate_len = (uint32_t)(n / 2 / ads->channels); /* intermediate_len counts samples per channel */ out_len = (uint32_t)(*sampc / 2); result=speex_resampler_process_interleaved_int( ads->resampler, ads->intermediate_buffer, &intermediate_len, sampv, &out_len); if (result!=RESAMPLER_ERR_SUCCESS) { warning("MPA dec upsample error: %s %d %d\n", strerror(result), out_len, *sampc/2); return EPROTO; } if (ads->channels==1) { for (i=out_len-1;i>=0;i--) sampv[i+i+1]=sampv[i+i]=sampv[i]; *sampc = out_len * 2; } else *sampc = out_len * ads->channels; } else { n /= 2; if (ads->channels!=1) { for (i=0;(unsigned)i<n;i++) sampv[i]=ads->intermediate_buffer[i]; *sampc = n; } else { for (i=0;(unsigned)i<n;i++) sampv[i*2]=sampv[i*2+1]= ads->intermediate_buffer[i]; *sampc = n * 2; } #ifdef DEBUG debug("MPA dec done %d\n",*sampc); #endif } return 0; }
/* This callback is called each time the sndstream driver needs some more data. It will tell us how much it needs in bytes. */ static void* mpg123_callback(snd_stream_hnd_t hnd, int size, int * actual) { //static int frames = 0; size_t done = 0; int err = 0; #ifdef BS_SIZE /* Check for file not started or file finished */ if (mp3_fd == 0) return NULL; #endif /* Dump the last PCM packet */ pcm_empty(pcm_discard); /* Loop decoding until we have a full buffer */ while (pcm_count < size) { #ifdef BS_SIZE /* Pull in some more data (and check for EOF) */ if (bs_fill() < 0 || bs_count < decinfo.framesize) { printf("snd_mp3_server: Decode completed\r\n"); goto errorout; } err = mpg123_decode(mh, bs_ptr, decinfo.framesize, pcm_ptr, size, &done); #else err = mpg123_read(mh, pcm_ptr, size, &done); #endif switch(err) { case MPG123_DONE: printf("snd_mp3_server: Decode completed\r\n"); goto errorout; case MPG123_NEED_MORE: printf("snd_mp3_server: MPG123_NEED_MORE\n"); break; case MPG123_ERR: printf("snd_mp3_server: %s\n", (char*)mpg123_strerror(mh)); goto errorout; break; default: break; } #ifdef BS_SIZE bs_ptr += decinfo.framesize; bs_count -= decinfo.framesize; #endif pcm_ptr += done; pcm_count += done; //frames++; //if (!(frames % 64)) { //printf("Decoded %d frames \r", frames); //} } pcm_discard = *actual = size; /* Got it successfully */ return pcm_buffer; errorout: #ifdef BS_SIZE fs_close(mp3_fd); mp3_fd = 0; #endif return NULL; }
static gboolean xmms_mpg123_init (xmms_xform_t *xform) { xmms_mpg123_data_t *data; const long *rates; size_t num_rates; int encoding; off_t length; int i, result; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_mpg123_data_t, 1); xmms_xform_private_data_set (xform, data); /* Get the total size of this stream and store it for later */ if (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE, &result)) { data->filesize = result; } mpg123_rates (&rates, &num_rates); data->param = mpg123_new_pars (&result); g_return_val_if_fail (data->param, FALSE); /* Create a quiet (stderr) decoder with auto choosen optimization. * Stuff set here should be tunable via plugin config properties! * You can also change some things during playback... */ mpg123_par (data->param, MPG123_ADD_FLAGS, MPG123_QUIET, 0); mpg123_par (data->param, MPG123_ADD_FLAGS, MPG123_GAPLESS, 0); /* choose: MPG123_RVA_OFF, MPG123_RVA_MIX, MPG123_RVA_ALBUM * xmms2 has its own ReplayGain plugin to handle the RVA field */ mpg123_par (data->param, MPG123_RVA, MPG123_RVA_OFF, 0); /* You could choose a decoder from the list provided by * mpg123_supported_decoders () and give that as second parameter. */ data->decoder = mpg123_parnew (data->param, NULL, &result); if (data->decoder == NULL) { xmms_log_error ("%s", mpg123_plain_strerror (result)); goto bad; } /* Prepare for buffer input feeding. */ result = mpg123_open_feed (data->decoder); if (result != MPG123_OK) { goto mpg123_bad; } /* Let's always decode to signed 16bit for a start. Any mpg123-supported sample rate is accepted. */ if (MPG123_OK != mpg123_format_none (data->decoder)) { goto mpg123_bad; } for (i = 0; i < num_rates; i++) { result = mpg123_format (data->decoder, rates[i], MPG123_MONO | MPG123_STEREO, MPG123_ENC_SIGNED_16); if (result != MPG123_OK) { goto mpg123_bad; } } /* Fetch ID3v1 data from the end of file if possible */ result = xmms_id3v1_get_tags (xform); if (result < 0) { xmms_log_error ("Seeking error when reading ID3v1 tags"); goto bad; } else if (data->filesize > result) { /* Reduce the size of tag data from the filesize */ data->filesize -= result; } /* Read data from input until decoded data is available from decoder */ do { /* Parse stream and get info. */ gint ret; xmms_error_t err; ret = xmms_xform_read (xform, data->buf, BUFSIZE, &err); if (ret < 0) { xmms_log_error ("Error when trying to find beginning of stream"); goto bad; } else if (ret == 0) { /* EOF reached before format was found, handled after loop */ break; } /* With zero output size nothing is actually outputted */ result = mpg123_decode (data->decoder, data->buf, (size_t) ret, NULL, 0, NULL); } while (result == MPG123_NEED_MORE); /* Keep feeding... */ if (result != MPG123_NEW_FORMAT) { xmms_log_error ("Unable to find beginning of stream (%s)!", result == MPG123_ERR ? mpg123_strerror (data->decoder) : "unexpected EOF"); goto bad; } result = mpg123_getformat (data->decoder, &data->samplerate, &data->channels, &encoding); if (result != MPG123_OK) { goto mpg123_bad; } /* Set the filesize so it can be used for duration estimation */ if (data->filesize > 0) { mpg123_set_filesize (data->decoder, data->filesize); } /* Get duration in samples, convert to ms and save to xmms2 */ length = mpg123_length (data->decoder); if (length > 0 && !xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, &i)) { length = (off_t) ((gfloat) length / data->samplerate * 1000); xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, (gint) length); } XMMS_DBG ("mpg123: got stream with %li Hz %i channels, encoding %i", data->samplerate, data->channels, encoding); xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, XMMS_STREAM_TYPE_FMT_CHANNELS, data->channels, XMMS_STREAM_TYPE_FMT_SAMPLERATE, (gint) data->samplerate, XMMS_STREAM_TYPE_END); return TRUE; mpg123_bad: xmms_log_error ("mpg123 error: %s", mpg123_strerror (data->decoder)); bad: mpg123_delete (data->decoder); mpg123_delete_pars (data->param); g_free (data); return FALSE; }
int _tmain(int argc, _TCHAR* argv[]) { mpg123_handle *m; int i; if (argc < 3) { fprintf(stderr, "\nI will give you the estimated and exact sample lengths of MPEG audio files.\n"); fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]); return -1; } mpg123_init(); m = mpg123_new(NULL, NULL); mpg123_param(m, MPG123_RESYNC_LIMIT, -1, 0); /* New in library version 0.0.1 . */ off_t a, b; if (MPG123_OK != mpg123_open_feed(m)) { fprintf(stderr, "open feed failed"); return -1; } FILE* file = _tfopen(argv[1], TEXT("rb")); if (!file) { fprintf(stderr, "open file failed"); return -1; } _stat64i32 st = { 0 }; _tstat(argv[1], &st); if (st.st_size <= 0) { fprintf(stderr, "file size is zero"); return -1; } char* pDataBuf = new char[st.st_size]; memset(pDataBuf, 0, st.st_size); if (st.st_size != fread(pDataBuf, 1, st.st_size, file)) { fprintf(stderr, "read file error"); return -1; } if (MPG123_OK != mpg123_feed(m, (const unsigned char*)pDataBuf, st.st_size)) { fprintf(stderr, "feed failed"); return -1; } // channels; bool bSaved = false; size_t nDone = 0; int res = mpg123_decode(m, NULL, 0, NULL, 0, &nDone); if (res == MPG123_NEW_FORMAT) { long rate = 0; int channels = 0; int enc = 0; mpg123_getformat(m, &rate, &channels, &enc); if (MPG123_ENC_SIGNED_16 == enc) { int nSamples = mpg123_length(m); int nBufCount = nSamples * channels; int nBufSize = nBufCount * sizeof(short); short* pBuf = new short[nBufCount]; res = mpg123_decode(m, NULL, 0, (unsigned char*)pBuf, nBufSize, &nDone); if (res == MPG123_OK) { KWavFile file; file.Init(pBuf, nDone, rate, ""); file.Save(CT2A(argv[2])); bSaved = true; } if (pBuf) { delete[] pBuf; pBuf = NULL; } } } mpg123_tclose(m); mpg123_delete(m); mpg123_exit(); return 0; }
size_t in_mp3_decode(plugin_obj *obj, uint8_t *in, size_t insz, uint8_t *out, size_t *outsz) { int r; size_t done; done = 0; // r = mpg123_decode((mpg123_handle *)obj->data, in, insz, out, outsz, &done); /* feed the decoder */ r = mpg123_feed((mpg123_handle *)obj->data, in, insz); if (r != MPG123_DONE) abort(); /* LULZ TODO XXX WTF */ /* read decoded data from internal buffer */ r = mpg123_read((mpg123_handle *)obj->data, out, *outsz, &done); /* increase buffer space if we need more space */ if (done > *outsz) { unsigned char *tmp; int newsz; newsz = done; tmp = malloc(newsz); memcpy(tmp, out, *outsz); r = mpg123_read((mpg123_handle *)obj->data, (tmp + *outsz), (newsz - *outsz), &done); assert(done == (newsz - *outsz)); assert(out != NULL); free(out); out = tmp; *outsz = newsz; } if (r == MPG123_NEW_FORMAT) { long rate; int chan, enc; mpg123_getformat((mpg123_handle *)obj->data, &rate, &chan, &enc); obj->channels = chan; /* XXX */ obj->rate = rate; /* TODO reinit output */ } #if 0 while(ret != MPG123_ERR && ret != MPG123_NEED_MORE) { /* Get all decoded audio that is available now before feeding more input. */ ret = mpg123_decode(m,NULL,0,out,OUTBUFF,&size); } #endif if (r == MPG123_ERR) return 0; return done; }
int32 nuiAudioDecoder::ReadIN(void* pBuffer, int32 sampleframes, nuiSampleBitFormat format) { if (!mInitialized) return 0; SetPosition(mPosition); int32 BitsPerSample = mInfo.GetBitsPerSample(); int32 channels = mInfo.GetChannels(); int32 frameSize = channels * (mInfo.GetBitsPerSample() / 8.f); int32 outBytes = sampleframes * frameSize; unsigned char* pTemp; bool allocated = false; if (BitsPerSample != 16 && BitsPerSample != 32) { NGL_ASSERT(0); return 0; } else if ( ((format == eSampleFloat32) && (BitsPerSample == 32)) || ((format == eSampleInt16) && (BitsPerSample == 16)) ) { pTemp = (unsigned char*)pBuffer; } else { pTemp = new unsigned char[outBytes]; allocated = true; } unsigned char* pIn = NULL; int32 bytesDone = 0; int err = MPG123_OK; int32 bytesRead = -1; while (outBytes && err != MPG123_DONE && bytesRead != 0) { size_t outBytesDone = 0; unsigned char* pOut = pTemp + bytesDone; err = mpg123_decode(mpPrivate->mpHandle, NULL, 0, pOut, outBytes, &outBytesDone); outBytes -= outBytesDone; bytesDone += outBytesDone; if (err == MPG123_NEW_FORMAT) { long r; int c; int e; mpg123_getformat(mpPrivate->mpHandle, &r, &c, &e); } // feed decoder if needed bytesRead = -1; while (err == MPG123_NEED_MORE && bytesRead != 0) { int32 inBytes = DECODER_INPUT_SIZE; if (!pIn) { pIn = new unsigned char[inBytes]; } bytesRead = mrStream.ReadUInt8(pIn, inBytes); err = mpg123_decode(mpPrivate->mpHandle, pIn, bytesRead, NULL, 0, &outBytesDone); } if (err != MPG123_OK && err != MPG123_DONE) { NGL_LOG("nuiAudioDecoder", NGL_LOG_INFO, "mpg123 error while decoding: %s", mpg123_strerror(mpPrivate->mpHandle)); } } int32 frames = bytesDone / frameSize; if (format == eSampleFloat32 && BitsPerSample == 16) { // convert '16 bits int' samples in pTemp to '32 bits float' samples in pBuffer int16* pSrc = (int16*)pTemp; float* pCopy = (float*)( ((int16*)pBuffer) + frames * channels ); float* pFloat = (float*)pBuffer; // copy int16 data to the second half of the output buffer // => nuiAudioConvert_16bitsBufferToFloat converts in place // 'int16' samples atored in the second half of the buffer are converted in 'float' samples filling all the buffer (sizeof(float) == 2 * sizeof(int16)) memcpy(pCopy, pSrc, frames * channels * sizeof(int16)); nuiAudioConvert_16bitsBufferToFloat(pFloat, frames * channels); // convert in place (int16 to float) } else if (format == eSampleInt16 && BitsPerSample == 32) { // convert '32 bits float' samples in pTemp to '16 bits int' samples in pBuffer float* pFloat = (float*)pTemp; int16* pInt16 = (int16*)pBuffer; nuiAudioConvert_FloatBufferTo16bits(pFloat, pInt16, frames * channels); } if (allocated) { delete[] pTemp; } if (pIn) { delete[] pIn; } mPosition += frames; return frames; }
bool FileFormatSupport( const char *fileE ) { FILE *f = qmp_fopen( fileE, "rb" ); if ( !f ) return 0; int _DATA_BUFF; if ( !getDataBuff( f, (size_t(*)(void *, size_t, size_t, void *))fread, _DATA_BUFF, NULL ) ) { fclose(f); return false; } int TagSize = _DATA_BUFF - DATA_BUFF; bool loaded(0); mpg123_handle *mus = mpg123_new(NULL, NULL); mpg123_open_feed( mus ); fseek(f,TagSize,0); char *data = new char[DATA_BUFF]; int bread = fread( data, 1, DATA_BUFF, f ); fclose(f); mpg123_decode( mus, (const unsigned char*)data, bread, 0,0,0 ); delete[] data; loaded = getMusInfo( mus, 0,0,0,0,0, -1, "" ); mpg123_close(mus); mpg123_delete(mus); return loaded; }
static int MP3_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, unsigned int channels, unsigned int rate, long h_codec ) { #ifndef WITH_MPG123DECODER ERROR("MP3 decoding support not compiled in.\n"); return -1; #else int res; size_t decoded_size; mp3_coder_state* coder_state; if (!h_codec) { ERROR("mp3 decoder not initialized!\n"); return -1; } coder_state = (mp3_coder_state*)h_codec; res = mpg123_decode(coder_state->mpg123_h, in_buf, size, out_buf, AUDIO_BUFFER_SIZE, &decoded_size); if (res == MPG123_NEW_FORMAT) { WARN("intermediate mp3 file format change!\n"); } if (res == MPG123_ERR) { ERROR("decoding mp3: '%s'\n", mpg123_strerror(coder_state->mpg123_h)); return -1; } /* DBG("mp3: decoded %d\n", decoded_size); */ return decoded_size; #endif }
static gint xmms_mpg123_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *err) { xmms_mpg123_data_t *data; int result = MPG123_OK; size_t read = 0; data = xmms_xform_private_data_get (xform); g_return_val_if_fail (data, -1); while (read == 0) { gint ret = 0; if (result == MPG123_NEED_MORE) { ret = xmms_xform_read (xform, data->buf, BUFSIZE, err); if (ret < 0) { return ret; } else if (ret == 0) { data->eof_found = TRUE; } } result = mpg123_decode (data->decoder, data->buf, (size_t) ret, buf, len, &read); if (result == MPG123_NEED_MORE && data->eof_found) { /* We need more data, but there's none available * so libmpg123 apparently missed an EOF */ result = MPG123_DONE; break; } else if (result != MPG123_OK && result != MPG123_NEED_MORE) { /* This is some uncommon result like EOF, handle outside * the loop */ break; } } if (result == MPG123_DONE) { /* This is just normal EOF reported from libmpg123 */ XMMS_DBG ("Got EOF while decoding stream"); return 0; } else if (result == MPG123_NEW_FORMAT) { /* FIXME: When we can handle format changes, modify this */ xmms_error_set (err, XMMS_ERROR_GENERIC, "The output format changed, XMMS2 can't handle that"); return -1; } else if (result == MPG123_ERR) { xmms_error_set (err, XMMS_ERROR_GENERIC, mpg123_strerror (data->decoder)); return -1; } return (gint) read; }