Mp3Decoder::~Mp3Decoder() { ExitRequested = true; while(Decoding) usleep(100); mad_synth_finish(&Synth); mad_frame_finish(&Frame); mad_stream_finish(&Stream); MEM2_free(ReadBuffer); }
static int stopread(sox_format_t * ft) { priv_t *p=(priv_t*) ft->priv; mad_synth_finish(&p->Synth); p->mad_frame_finish(&p->Frame); p->mad_stream_finish(&p->Stream); free(p->mp3_buffer); LSX_DLLIBRARY_CLOSE(p, mad_dl); return SOX_SUCCESS; }
// // madx_deinit(): // // Close files, free memory allocated for // structures. // void madx_deinit (madx_house *mxhouse) { // Mad is no longer used, the structures // that were initialized must now be // cleared. mad_synth_finish(&mxhouse->synth); mad_frame_finish(&mxhouse->frame); mad_stream_finish(&mxhouse->stream); }
static void mp3_close (void *void_data) { struct mp3_data *data = (struct mp3_data *)void_data; if (data->ok) { io_close (data->io_stream); mad_stream_finish (&data->stream); mad_frame_finish (&data->frame); mad_synth_finish (&data->synth); } decoder_error_clear (&data->error); free (data); }
static void mad_dispose (audio_decoder_t *this_gen) { mad_decoder_t *this = (mad_decoder_t *) this_gen; mad_synth_finish (&this->synth); mad_frame_finish (&this->frame); mad_stream_finish(&this->stream); if (this->output_open) { this->xstream->audio_out->close (this->xstream->audio_out, this->xstream); this->output_open = 0; } free (this_gen); }
static void close_mad(bgav_stream_t * s) { mad_priv_t * priv; priv = s->decoder_priv; mad_synth_finish(&priv->synth); mad_frame_finish(&priv->frame); mad_stream_finish(&priv->stream); bgav_bytebuffer_free(&priv->buf); if(priv->audio_frame) gavl_audio_frame_destroy(priv->audio_frame); free(priv); }
static void mad_reset (audio_decoder_t *this_gen) { mad_decoder_t *this = (mad_decoder_t *) this_gen; mad_synth_finish (&this->synth); mad_frame_finish (&this->frame); mad_stream_finish(&this->stream); this->pts = 0; this->bytes_in_buffer = 0; this->preview_mode = 0; mad_synth_init (&this->synth); mad_stream_init (&this->stream); mad_frame_init (&this->frame); }
void MP3_FreeTune() { # ifndef LINUX_MODE /* The input file was completely read; the memory allocated by our * reading module must be reclaimed. */ if (mp3_data) { free(mp3_data); mp3_data = 0; } /* Mad is no longer used, the structures that were initialized must * now be cleared. */ mad_synth_finish(&Synth); mad_frame_finish(&Frame); mad_stream_finish(&Stream); # endif }
int Mp3Decoder::Rewind() { mad_synth_finish(&Synth); mad_frame_finish(&Frame); mad_stream_finish(&Stream); mad_timer_reset(&Timer); mad_stream_init(&Stream); mad_frame_init(&Frame); mad_synth_init(&Synth); SynthPos = 0; GuardPtr = NULL; if(!file_fd) return -1; return SoundDecoder::Rewind(); }
void MADTranscode::clearBuffers() { mad_synth_finish( &synth ); mad_frame_finish( &frame ); mad_stream_finish( &stream ); m_mpegInitialised = false; timer = mad_timer_zero; last_timer = mad_timer_zero; m_encodedBuffer.clear(); m_decodedBuffer.clear(); mad_stream_init( &stream ); mad_frame_init( &frame ); mad_synth_init( &synth ); }
/** * 停止MP3音乐文件的播放,销毁所占有的线程、资源等 * * @note 不可以在播放线程中调用,必须能够多次重复调用而不死机 * * @return 成功时返回0 */ static int mp3_end(void) { dbg_printf(d, "%s", __func__); __end(); xAudioEnd(); g_status = ST_STOPPED; mad_stream_finish(&stream); mad_synth_finish(&synth); mad_frame_finish(&frame); if (use_me) { if (mp3_getEDRAM) xrAudiocodecReleaseEDRAM(mp3_codec_buffer); } free_mp3_info(&mp3info); free_bitrate(&g_inst_br); if (mp3_data.use_buffer) { if (mp3_data.r != NULL) { buffered_reader_close(mp3_data.r); mp3_data.r = NULL; } } else { if (mp3_data.fd >= 0) { xrIoClose(mp3_data.fd); mp3_data.fd = -1; } } if (g_buff != NULL) { xAudioFree(g_buff); g_buff = NULL; } generic_end(); return 0; }
static void resync_mad(bgav_stream_t * s) { mad_priv_t * priv; priv = s->decoder_priv; priv->eof = 0; priv->partial = 0; mad_frame_finish(&priv->frame); mad_synth_finish(&priv->synth); mad_stream_finish(&priv->stream); // fprintf(stderr, "Resync mad\n"); bgav_bytebuffer_flush(&priv->buf); mad_frame_init(&priv->frame); mad_synth_init(&priv->synth); mad_stream_init(&priv->stream); get_data(s); }
static void mad_reset (audio_decoder_t *this_gen) { mad_decoder_t *this = (mad_decoder_t *) this_gen; mad_synth_finish (&this->synth); mad_frame_finish (&this->frame); mad_stream_finish(&this->stream); this->pts = 0; this->bytes_in_buffer = 0; this->preview_mode = 0; this->start_padding = 0; this->end_padding = 0; this->needs_more_data = 0; mad_synth_init (&this->synth); mad_stream_init (&this->stream); this->stream.options = MAD_OPTION_IGNORECRC; mad_frame_init (&this->frame); }
SINT SoundSourceMp3::restartDecoding( const SeekFrameType& seekFrame) { qDebug() << "restartDecoding @" << seekFrame.frameIndex; // Discard decoded output m_madSynthCount = 0; if (getMinFrameIndex() == seekFrame.frameIndex) { mad_frame_finish(&m_madFrame); mad_synth_finish(&m_madSynth); } mad_stream_finish(&m_madStream); mad_stream_init(&m_madStream); mad_stream_options(&m_madStream, MAD_OPTION_IGNORECRC); if (getMinFrameIndex() == seekFrame.frameIndex) { mad_synth_init(&m_madSynth); mad_frame_init(&m_madFrame); } // Fill input buffer mad_stream_buffer(&m_madStream, seekFrame.pInputData, m_fileSize - (seekFrame.pInputData - m_pFileData)); if (getMinFrameIndex() < seekFrame.frameIndex) { // Muting is done here to eliminate potential pops/clicks // from skipping Rob Leslie explains why here: // http://www.mars.org/mailman/public/mad-dev/2001-August/000321.html mad_frame_mute(&m_madFrame); mad_synth_mute(&m_madSynth); } if (!decodeFrameHeader(&m_madFrame.header, &m_madStream, false)) { if (!isStreamValid(m_madStream)) { // Failure -> Seek to EOF return getFrameCount(); } } return seekFrame.frameIndex; }
void CDVDAudioCodecLibMad::Reset() { if (m_bInitialized) { mad_synth_finish(&m_synth); m_dll.mad_stream_finish(&m_stream); m_dll.mad_frame_finish(&m_frame); m_dll.mad_synth_init(&m_synth); m_dll.mad_stream_init(&m_stream); m_dll.mad_frame_init(&m_frame); m_stream.options = MAD_OPTION_IGNORECRC; m_iDecodedDataSize = 0; m_iSourceSampleRate = 0; m_iSourceChannels = 0; m_iSourceBitrate = 0; m_iInputBufferSize = 0; } }
static void xmms_mad_destroy (xmms_xform_t *xform) { xmms_mad_data_t *data; g_return_if_fail (xform); data = xmms_xform_private_data_get (xform); g_return_if_fail (data); mad_stream_finish (&data->stream); mad_frame_finish (&data->frame); mad_synth_finish (&data->synth); if (data->xing) { xmms_xing_free (data->xing); } g_free (data); }
static void mad_close(input_object *obj) { struct mad_local_data *data; if (!obj) return; data = (struct mad_local_data *)obj->local_data; if (data) { if (data->mad_fd) reader_close(data->mad_fd); if (data->mad_init) { mad_synth_finish (&data->synth); mad_frame_finish (&data->frame); mad_stream_finish(&data->stream); data->mad_init = 0; } if (data->frames) { free(data->frames); } free(obj->local_data); obj->local_data = NULL; } }
void FreeTune() { mad_synth_finish(&synth); mad_frame_finish(&frame); mad_stream_finish(&stream); };
// MP3 decode player void MP3Player(void) { FRESULT res; uint8_t *ReadStart; uint8_t *GuardPtr; volatile uint8_t u8PCMBufferTargetIdx = 0; volatile uint32_t pcmbuf_idx, i; volatile unsigned int Mp3FileOffset=0; uint16_t sampleL, sampleR; pcmbuf_idx = 0; memset((void *)&audioInfo, 0, sizeof(audioInfo)); /* Parse MP3 header */ MP3_ParseHeaderInfo(MP3_FILE); /* First the structures used by libmad must be initialized. */ mad_stream_init(&Stream); mad_frame_init(&Frame); mad_synth_init(&Synth); /* Open MP3 file */ res = f_open(&mp3FileObject, MP3_FILE, FA_OPEN_EXISTING | FA_READ); if (res != FR_OK) { printf("Open file error \r\n"); return; } /* Open I2S1 interface and set to slave mode, stereo channel, I2S format */ I2S_Open(I2S1, I2S_MODE_SLAVE, 16000, I2S_DATABIT_16, I2S_STEREO, I2S_FORMAT_I2S, I2S_I2S); /* Initialize WAU8822 codec */ WAU8822_Setup(); /* Configure wau8822 for specific sampling rate */ WAU8822_ConfigSampleRate(audioInfo.mp3SampleRate); /* Set MCLK and enable MCLK */ I2S_EnableMCLK(I2S1, 12000000); while(1) { if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) { if(Stream.next_frame != NULL) { /* Get the remaining frame */ Remaining = Stream.bufend - Stream.next_frame; memmove(MadInputBuffer, Stream.next_frame, Remaining); ReadStart = MadInputBuffer + Remaining; ReadSize = FILE_IO_BUFFER_SIZE - Remaining; } else { ReadSize = FILE_IO_BUFFER_SIZE, ReadStart = MadInputBuffer, Remaining = 0; } /* read the file from SDCard */ res = f_read(&mp3FileObject, ReadStart, ReadSize, &ReturnSize); if((res != FR_OK) || f_eof(&mp3FileObject)) { printf("Stop !(%x)\n\r", res); goto stop; } /* if the file is over */ if (ReadSize > ReturnSize) { GuardPtr=ReadStart+ReadSize; memset(GuardPtr,0,MAD_BUFFER_GUARD); ReadSize+=MAD_BUFFER_GUARD; } Mp3FileOffset = Mp3FileOffset + ReturnSize; /* Pipe the new buffer content to libmad's stream decoder * facility. */ mad_stream_buffer(&Stream,MadInputBuffer,ReadSize+Remaining); Stream.error=(enum mad_error)0; } /* decode a frame from the mp3 stream data */ if(mad_frame_decode(&Frame,&Stream)) { if(MAD_RECOVERABLE(Stream.error)) { /*if(Stream.error!=MAD_ERROR_LOSTSYNC || Stream.this_frame!=GuardPtr) { }*/ continue; } else { /* the current frame is not full, need to read the remaining part */ if(Stream.error==MAD_ERROR_BUFLEN) { continue; } else { printf("Something error!!\n"); /* play the next file */ audioInfo.mp3FileEndFlag = 1; goto stop; } } } /* Once decoded the frame is synthesized to PCM samples. No errors * are reported by mad_synth_frame(); */ mad_synth_frame(&Synth,&Frame); // // decode finished, try to copy pcm data to audio buffer // if(audioInfo.mp3Playing) { //if next buffer is still full (playing), wait until it's empty if(aPCMBuffer_Full[u8PCMBufferTargetIdx] == 1) while(aPCMBuffer_Full[u8PCMBufferTargetIdx]); } else { if((aPCMBuffer_Full[0] == 1) && (aPCMBuffer_Full[1] == 1 )) { //all buffers are full, wait StartPlay(); } } for(i=0; i<(int)Synth.pcm.length; i++) { /* Get the left/right samples */ sampleL = Synth.pcm.samples[0][i]; sampleR = Synth.pcm.samples[1][i]; /* Fill PCM data to I2S(PDMA) buffer */ aPCMBuffer[u8PCMBufferTargetIdx][pcmbuf_idx++] = sampleR | (sampleL << 16); /* Need change buffer ? */ if(pcmbuf_idx == PCM_BUFFER_SIZE) { aPCMBuffer_Full[u8PCMBufferTargetIdx] = 1; //set full flag u8PCMBufferTargetIdx ^= 1; pcmbuf_idx = 0; // printf("change to ==>%d ..\n", u8PCMBufferTargetIdx); /* if next buffer is still full (playing), wait until it's empty */ if((aPCMBuffer_Full[u8PCMBufferTargetIdx] == 1) && (audioInfo.mp3Playing)) while(aPCMBuffer_Full[u8PCMBufferTargetIdx]); } } } stop: printf("Exit MP3\r\n"); mad_synth_finish(&Synth); mad_frame_finish(&Frame); mad_stream_finish(&Stream); f_close(&mp3FileObject); StopPlay(); }
void SoundSourceMp3::finishDecoding() { m_madSynthCount = 0; mad_synth_finish(&m_madSynth); mad_frame_finish(&m_madFrame); mad_stream_finish(&m_madStream); }
/* player thread; for every song a new thread is started * @param aacPlayer structure * @return NULL NULL NULL ... */ void *BarPlayerThread (void *data) { struct audioPlayer *player = data; char extraHeaders[25]; void *ret = PLAYER_RET_OK; #ifdef ENABLE_FAAD NeAACDecConfigurationPtr conf; #endif WaitressReturn_t wRet = WAITRESS_RET_ERR; /* init handles */ pthread_mutex_init (&player->pauseMutex, NULL); player->scale = computeReplayGainScale (player->gain); player->waith.data = (void *) player; /* extraHeaders will be initialized later */ player->waith.extraHeaders = extraHeaders; switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: player->aacHandle = NeAACDecOpen(); /* set aac conf */ conf = NeAACDecGetCurrentConfiguration(player->aacHandle); conf->outputFormat = FAAD_FMT_16BIT; conf->downMatrix = 1; NeAACDecSetConfiguration(player->aacHandle, conf); player->waith.callback = BarPlayerAACCb; break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: case PIANO_AF_MP3_HI: mad_stream_init (&player->mp3Stream); mad_frame_init (&player->mp3Frame); mad_synth_init (&player->mp3Synth); player->waith.callback = BarPlayerMp3Cb; break; #endif /* ENABLE_MAD */ default: printf("Unsupported audio format!\n"); return PLAYER_RET_OK; break; } player->mode = PLAYER_INITIALIZED; /* This loop should work around song abortions by requesting the * missing part of the song */ do { snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n", player->bytesReceived); wRet = WaitressFetchCall (&player->waith); } while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT || wRet == WAITRESS_RET_READ_ERR); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: NeAACDecClose(player->aacHandle); break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: case PIANO_AF_MP3_HI: mad_synth_finish (&player->mp3Synth); mad_frame_finish (&player->mp3Frame); mad_stream_finish (&player->mp3Stream); break; #endif /* ENABLE_MAD */ default: /* this should never happen: thread is aborted above */ break; } if (player->aoError) { ret = (void *) PLAYER_RET_ERR; } if (player->audioOutDevice) ao_close(player->audioOutDevice); WaitressFree (&player->waith); #ifdef ENABLE_FAAD if (player->sampleSize != NULL) { free (player->sampleSize); } #endif /* ENABLE_FAAD */ pthread_mutex_destroy (&player->pauseMutex); player->mode = PLAYER_FINISHED_PLAYBACK; return ret; }
static void MP3Update(void) { int flip; UINT8 *GuardPtr; INT16 *OutputPtr, *OutputEnd; struct mad_stream Stream; struct mad_frame Frame; struct mad_synth Synth; mad_timer_t Timer; mad_stream_init(&Stream); mad_frame_init(&Frame); mad_synth_init(&Synth); mad_timer_reset(&Timer); OutputPtr = (INT16 *)mp3_out[0]; OutputEnd = (INT16 *)(mp3_out[0] + MP3_BUFFER_SIZE); GuardPtr = NULL; mp3_filepos = 0; mp3_frame = 0; flip = 0; cdda_command_ack = 1; while (mp3_active && mp3_status != MP3_STOP) { if (Stream.buffer == NULL || Stream.error == MAD_ERROR_BUFLEN) { UINT32 ReadSize, Remaining; UINT8 *ReadStart; if (Stream.next_frame != NULL) { Remaining = Stream.bufend - Stream.next_frame; ReadStart = mp3_in + Remaining; ReadSize = (2 * MP3_BUFFER_SIZE) - Remaining; memmove(mp3_in, Stream.next_frame, Remaining); } else { ReadSize = 2 * MP3_BUFFER_SIZE; ReadStart = mp3_in; Remaining = 0; } if (MP3SleepCheck()) break; ReadSize = sceIoRead(mp3_fd, ReadStart, ReadSize); mp3_filepos += ReadSize; if (mp3_filepos == mp3_fsize) { if (cdda_autoloop) { mp3_filepos = 0; sceIoLseek(mp3_fd, 0, PSP_SEEK_SET); } else { cdda_playing = CDDA_STOP; mp3_status = MP3_STOP; } } if (mp3_filepos == mp3_fsize) { GuardPtr = ReadStart + ReadSize; memset(GuardPtr, 0, MAD_BUFFER_GUARD); ReadSize += MAD_BUFFER_GUARD; } mad_stream_buffer(&Stream, mp3_in, ReadSize + Remaining); Stream.error = 0; } if (mad_frame_decode(&Frame, &Stream)) { if (MAD_RECOVERABLE(Stream.error)) { // if (Stream.error != MAD_ERROR_LOSTSYNC || Stream.this_frame != GuardPtr) continue; } else if (Stream.error == MAD_ERROR_BUFLEN) { continue; } else { ui_popup(TEXT(MP3_DECODE_ERROR)); mp3_status = MP3_STOP; break; } } mp3_frame++; mad_timer_add(&Timer, Frame.header.duration); mad_synth_frame(&Synth, &Frame); if (mp3_status == MP3_PLAY) { int i; for (i = 0; i < Synth.pcm.length; i++) { if (MAD_NCHANNELS(&Frame.header) == 2) { *OutputPtr++ = MP3Limit(Synth.pcm.samples[0][i]); *OutputPtr++ = MP3Limit(Synth.pcm.samples[1][i]); } else { INT16 data = MP3Limit(Synth.pcm.samples[0][i]); *OutputPtr++ = data; *OutputPtr++ = data; } if (OutputPtr == OutputEnd) { sceAudioOutputPannedBlocking(mp3_handle, mp3_volume, mp3_volume, mp3_out[flip]); flip ^= 1; OutputPtr = (INT16 *)mp3_out[flip]; OutputEnd = (INT16 *)(mp3_out[flip] + MP3_BUFFER_SIZE); } } } else if (mp3_status == MP3_SEEK) { if (mp3_frame >= mp3_start_frame) { mp3_start_frame = 0; mp3_status = MP3_SLEEP; sceKernelSleepThread(); } } } mad_synth_finish(&Synth); mad_frame_finish(&Frame); mad_stream_finish(&Stream); if (mp3_fd >= 0) { sceIoClose(mp3_fd); mp3_fd = -1; } }
long madaudiofile::update_duration(FILE *f) { bool oldEOF = reachedEOF; reachedEOF = false; current_pos = 0; frame_count = 0; outputLength = 0; outputPosition = 0; // samplerate = 44100; samplerate = 16000; //bool firstRun = true; if (!f) throw "madaudiofile::update_duration(): file is not opened\n"; fpos_t oldPosition; fgetpos(f,&oldPosition); fseek(f, 0, SEEK_SET); /* struct mad_header m_header; mad_timer_reset(Timer); while(!reachedEOF) { if(Stream->buffer==NULL || Stream->error==MAD_ERROR_BUFLEN || firstRun) { firstRun = false; size_t ReadSize,Remaining; unsigned char *ReadStart; u_int8_t *GuardPtr = NULL; if(Stream->next_frame!=NULL) { Remaining=Stream->bufend-Stream->next_frame; memmove(InputBuffer,Stream->next_frame,Remaining); ReadStart=InputBuffer+Remaining; ReadSize=INPUT_BUFFER_SIZE-Remaining; } else { ReadSize=INPUT_BUFFER_SIZE; ReadStart=InputBuffer; Remaining=0; } ReadSize = readData(ReadStart,1,ReadSize,f); if(ReadSize <= 0) throw "Madaudiofile: could not read from file\n"; if(reachedEOF) { GuardPtr=ReadStart+ReadSize; memset(GuardPtr,0,MAD_BUFFER_GUARD); ReadSize+=MAD_BUFFER_GUARD; } mad_stream_buffer(Stream,InputBuffer,ReadSize); } while(1) { if( mad_header_decode(&m_header, Stream) == -1 ) { if( MAD_RECOVERABLE(Stream->error) ) { continue; } else if( Stream->error == MAD_ERROR_BUFLEN ) { break; // EOF } else { break; // BAD ERROR, oh well } } mad_timer_add(Timer, m_header.duration); } } */ double dur = 0; /*while(!eof()) */{ audiodata ad = getNextAudioSlice(1000, false); dur += ad.getDuration(); } duration = (long int) dur; fsetpos(f,&oldPosition); /* duration = mad_timer_count(*Timer, MAD_UNITS_MILLISECONDS); mad_header_finish(&m_header); */ #ifdef HAVE_MAD_H mad_synth_finish(Synth); mad_frame_finish(Frame); mad_stream_finish(Stream); memset(OutputBuffer, 0, OUTPUT_BUFFER_SIZE); memset(InputBuffer, 0, INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD); mad_stream_init(Stream); mad_frame_init(Frame); mad_synth_init(Synth); mad_timer_reset(Timer); Stream->error=(mad_error)0; #endif // HAVE_MAD_H reachedEOF = oldEOF; #ifdef MADAUDIO_PRINT_DEBUG printf("Got duration %li\n",duration); #endif return duration; }
/* player thread; for every song a new thread is started * @param audioPlayer structure * @return PLAYER_RET_* */ void *BarPlayerThread (void *data) { struct audioPlayer *player = data; char extraHeaders[32]; void *ret = PLAYER_RET_OK; #ifdef ENABLE_FAAD NeAACDecConfigurationPtr conf; #endif WaitressReturn_t wRet = WAITRESS_RET_ERR; /* init handles */ player->waith.data = (void *) player; /* extraHeaders will be initialized later */ player->waith.extraHeaders = extraHeaders; player->buffer = malloc (BAR_PLAYER_BUFSIZE); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: player->aacHandle = NeAACDecOpen(); /* set aac conf */ conf = NeAACDecGetCurrentConfiguration(player->aacHandle); conf->outputFormat = FAAD_FMT_16BIT; conf->downMatrix = 1; NeAACDecSetConfiguration(player->aacHandle, conf); player->waith.callback = BarPlayerAACCb; break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_stream_init (&player->mp3Stream); mad_frame_init (&player->mp3Frame); mad_synth_init (&player->mp3Synth); player->waith.callback = BarPlayerMp3Cb; break; #endif /* ENABLE_MAD */ default: /* FIXME: leaks memory */ BarUiMsg (player->settings, MSG_ERR, "Unsupported audio format!\n"); return PLAYER_RET_OK; break; } player->mode = PLAYER_INITIALIZED; /* This loop should work around song abortions by requesting the * missing part of the song */ do { snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n", player->bytesReceived); wRet = WaitressFetchCall (&player->waith); } while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT || wRet == WAITRESS_RET_READ_ERR); /* If the song was played all the way through tag it. */ if (wRet == WAITRESS_RET_OK) { BarFlyTag(&player->fly, player->settings); } switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: NeAACDecClose(player->aacHandle); free (player->sampleSize); break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_synth_finish (&player->mp3Synth); mad_frame_finish (&player->mp3Frame); mad_stream_finish (&player->mp3Stream); break; #endif /* ENABLE_MAD */ default: /* this should never happen: thread is aborted above */ break; } if (player->aoError) { ret = (void *) PLAYER_RET_ERR; } ao_close(player->audioOutDevice); WaitressFree (&player->waith); free (player->buffer); player->mode = PLAYER_FINISHED_PLAYBACK; return ret; }
static int run_sync(struct mad_decoder *decoder) { enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); void *error_data; int bad_last_frame = 0; struct mad_stream *stream; struct mad_frame *frame; struct mad_synth *synth; int result = 0; if (decoder->input_func == 0) return 0; if (decoder->error_func) { error_func = decoder->error_func; error_data = decoder->cb_data; } else { error_func = error_default; error_data = &bad_last_frame; } stream = &decoder->sync->stream; frame = &decoder->sync->frame; synth = &decoder->sync->synth; mad_stream_init(stream); mad_frame_init(frame); mad_synth_init(synth); mad_stream_options(stream, decoder->options); do { switch (decoder->input_func(decoder->cb_data, stream)) { case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: continue; case MAD_FLOW_CONTINUE: break; } while (1) { if (decoder->header_func) { if (mad_header_decode(&frame->header, stream) == -1) { if (!MAD_RECOVERABLE(stream->error)) break; switch (error_func(error_data, stream, frame)) { case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: case MAD_FLOW_CONTINUE: default: continue; } } switch (decoder->header_func(decoder->cb_data, &frame->header)) { case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: continue; case MAD_FLOW_CONTINUE: break; } } if (mad_frame_decode(frame, stream) == -1) { if (!MAD_RECOVERABLE(stream->error)) break; switch (error_func(error_data, stream, frame)) { case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: break; case MAD_FLOW_CONTINUE: default: continue; } } else bad_last_frame = 0; if (decoder->filter_func) { switch (decoder->filter_func(decoder->cb_data, stream, frame)) { case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: continue; case MAD_FLOW_CONTINUE: break; } } mad_synth_frame(synth, frame); if (decoder->output_func) { switch (decoder->output_func(decoder->cb_data, &frame->header, &synth->pcm)) { case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: case MAD_FLOW_CONTINUE: break; } } } } while (stream->error == MAD_ERROR_BUFLEN); fail: result = -1; done: mad_synth_finish(synth); mad_frame_finish(frame); mad_stream_finish(stream); return result; }
MadSynth::~MadSynth() { mad_synth_finish(this); }
static gboolean xmms_mad_init (xmms_xform_t *xform) { struct mad_frame frame; struct mad_stream stream; xmms_error_t err; guchar buf[40960]; xmms_mad_data_t *data; int len; const gchar *metakey; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_mad_data_t, 1); mad_stream_init (&data->stream); mad_frame_init (&data->frame); mad_synth_init (&data->synth); xmms_xform_private_data_set (xform, data); data->buffer_length = 0; data->synthpos = 0x7fffffff; mad_stream_init (&stream); mad_frame_init (&frame); len = xmms_xform_peek (xform, buf, 40960, &err); mad_stream_buffer (&stream, buf, len); while (mad_frame_decode (&frame, &stream) == -1) { if (!MAD_RECOVERABLE (stream.error)) { XMMS_DBG ("couldn't decode %02x %02x %02x %02x",buf[0],buf[1],buf[2],buf[3]); mad_frame_finish (&frame); mad_stream_finish (&stream); return FALSE; } } data->channels = frame.header.mode == MAD_MODE_SINGLE_CHANNEL ? 1 : 2; data->samplerate = frame.header.samplerate; if (frame.header.flags & MAD_FLAG_PROTECTION) { XMMS_DBG ("Frame has protection enabled"); if (stream.anc_ptr.byte > stream.buffer + 2) { stream.anc_ptr.byte = stream.anc_ptr.byte - 2; } } data->samples_to_play = -1; data->xing = xmms_xing_parse (stream.anc_ptr); if (data->xing) { xmms_xing_lame_t *lame; XMMS_DBG ("File with Xing header!"); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_IS_VBR; xmms_xform_metadata_set_int (xform, metakey, 1); if (xmms_xing_has_flag (data->xing, XMMS_XING_FRAMES)) { guint duration; mad_timer_t timer; timer = frame.header.duration; mad_timer_multiply (&timer, xmms_xing_get_frames (data->xing)); duration = mad_timer_count (timer, MAD_UNITS_MILLISECONDS); XMMS_DBG ("XING duration %d", duration); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, duration); if (xmms_xing_has_flag (data->xing, XMMS_XING_BYTES) && duration) { guint tmp; tmp = xmms_xing_get_bytes (data->xing) * ((guint64)8000) / duration; XMMS_DBG ("XING bitrate %d", tmp); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, tmp); } } lame = xmms_xing_get_lame (data->xing); if (lame) { /* FIXME: add a check for ignore_lame_headers from the medialib */ data->frames_to_skip = 1; data->samples_to_skip = lame->start_delay; data->samples_to_play = ((guint64) xmms_xing_get_frames (data->xing) * 1152ULL) - lame->start_delay - lame->end_padding; XMMS_DBG ("Samples to skip in the beginning: %d, total: %" G_GINT64_FORMAT, data->samples_to_skip, data->samples_to_play); /* metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_ALBUM; xmms_xform_metadata_set_int (xform, metakey, lame->audiophile_gain); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PEAK_TRACK; xmms_xform_metadata_set_int (xform, metakey, lame->peak_amplitude); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK; xmms_xform_metadata_set_int (xform, metakey, lame->radio_gain); */ } } else { gint filesize; metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE; xmms_xform_metadata_set_int (xform, metakey, frame.header.bitrate); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; if (!xmms_xform_metadata_get_int (xform, metakey, &filesize)) { metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE; if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) { gint32 val; val = (gint32) (filesize * (gdouble) 8000.0 / frame.header.bitrate); metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION; xmms_xform_metadata_set_int (xform, metakey, val); } } } /* seeking needs bitrate */ data->bitrate = frame.header.bitrate; if (xmms_id3v1_get_tags (xform) < 0) { mad_stream_finish (&data->stream); mad_frame_finish (&data->frame); mad_synth_finish (&data->synth); if (data->xing) { xmms_xing_free (data->xing); } return FALSE; } 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, data->samplerate, XMMS_STREAM_TYPE_END); mad_frame_finish (&frame); mad_stream_finish (&stream); return TRUE; }
static int sox_mp3seek(sox_format_t * ft, uint64_t offset) { priv_t * p = (priv_t *) ft->priv; size_t initial_bitrate = p->Frame.header.bitrate; size_t tagsize = 0, consumed = 0; sox_bool vbr = sox_false; /* Variable Bit Rate */ sox_bool depadded = sox_false; uint64_t to_skip_samples = 0; /* Reset all */ rewind((FILE*)ft->fp); mad_timer_reset(&p->Timer); p->FrameCount = 0; /* They where opened in startread */ mad_synth_finish(&p->Synth); p->mad_frame_finish(&p->Frame); p->mad_stream_finish(&p->Stream); p->mad_stream_init(&p->Stream); p->mad_frame_init(&p->Frame); p->mad_synth_init(&p->Synth); offset /= ft->signal.channels; to_skip_samples = offset; while(sox_true) { /* Read data from the MP3 file */ int read, padding = 0; size_t leftover = p->Stream.bufend - p->Stream.next_frame; memcpy(p->mp3_buffer, p->Stream.this_frame, leftover); read = fread(p->mp3_buffer + leftover, (size_t) 1, p->mp3_buffer_size - leftover, (FILE*)ft->fp); if (read <= 0) { lsx_debug("seek failure. unexpected EOF (frames=%" PRIuPTR " leftover=%" PRIuPTR ")", p->FrameCount, leftover); break; } for (; !depadded && padding < read && !p->mp3_buffer[padding]; ++padding); depadded = sox_true; p->mad_stream_buffer(&p->Stream, p->mp3_buffer + padding, leftover + read - padding); while (sox_true) { /* Decode frame headers */ static unsigned short samples; p->Stream.error = MAD_ERROR_NONE; /* Not an audio frame */ if (p->mad_header_decode(&p->Frame.header, &p->Stream) == -1) { if (p->Stream.error == MAD_ERROR_BUFLEN) break; /* Normal behaviour; get some more data from the file */ if (!MAD_RECOVERABLE(p->Stream.error)) { lsx_warn("unrecoverable MAD error"); break; } if (p->Stream.error == MAD_ERROR_LOSTSYNC) { unsigned available = (p->Stream.bufend - p->Stream.this_frame); tagsize = tagtype(p->Stream.this_frame, (size_t) available); if (tagsize) { /* It's some ID3 tags, so just skip */ if (tagsize >= available) { fseeko((FILE*)ft->fp, (off_t)(tagsize - available), SEEK_CUR); depadded = sox_false; } p->mad_stream_skip(&p->Stream, min(tagsize, available)); } else lsx_warn("MAD lost sync"); } else lsx_warn("recoverable MAD error"); continue; } consumed += p->Stream.next_frame - p->Stream.this_frame; vbr |= (p->Frame.header.bitrate != initial_bitrate); samples = 32 * MAD_NSBSAMPLES(&p->Frame.header); p->FrameCount++; p->mad_timer_add(&p->Timer, p->Frame.header.duration); if(to_skip_samples <= samples) { p->mad_frame_decode(&p->Frame,&p->Stream); p->mad_synth_frame(&p->Synth, &p->Frame); p->cursamp = to_skip_samples; return SOX_SUCCESS; } else to_skip_samples -= samples; /* If not VBR, we can extrapolate frame size */ if (p->FrameCount == 64 && !vbr) { p->FrameCount = offset / samples; to_skip_samples = offset % samples; if (SOX_SUCCESS != lsx_seeki(ft, (off_t)(p->FrameCount * consumed / 64 + tagsize), SEEK_SET)) return SOX_EOF; /* Reset Stream for refilling buffer */ p->mad_stream_finish(&p->Stream); p->mad_stream_init(&p->Stream); break; } } }; return SOX_EOF; }
/* player thread; for every song a new thread is started * @param audioPlayer structure * @return PLAYER_RET_* */ void *BarPlayerThread (void *data) { struct audioPlayer *player = data; char extraHeaders[32]; void *ret = PLAYER_RET_OK; #ifdef ENABLE_FAAD NeAACDecConfigurationPtr conf; #endif WaitressReturn_t wRet = WAITRESS_RET_ERR; /* init handles */ pthread_mutex_init (&player->pauseMutex, NULL); player->waith.data = (void *) player; /* extraHeaders will be initialized later */ player->waith.extraHeaders = extraHeaders; player->buffer = malloc (BAR_PLAYER_BUFSIZE); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: player->aacHandle = NeAACDecOpen(); /* set aac conf */ conf = NeAACDecGetCurrentConfiguration(player->aacHandle); conf->outputFormat = FAAD_FMT_16BIT; conf->downMatrix = 1; NeAACDecSetConfiguration(player->aacHandle, conf); player->waith.callback = BarPlayerAACCb; break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_stream_init (&player->mp3Stream); mad_frame_init (&player->mp3Frame); mad_synth_init (&player->mp3Synth); player->waith.callback = BarPlayerMp3Cb; break; #endif /* ENABLE_MAD */ default: BarUiMsg (player->settings, MSG_ERR, "Unsupported audio format!\n"); ret = (void *) PLAYER_RET_HARDFAIL; goto cleanup; break; } player->mode = PLAYER_INITIALIZED; /* This loop should work around song abortions by requesting the * missing part of the song */ do { snprintf (extraHeaders, sizeof (extraHeaders), "Range: bytes=%zu-\r\n", player->bytesReceived); wRet = WaitressFetchCall (&player->waith); } while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT || wRet == WAITRESS_RET_READ_ERR); switch (player->audioFormat) { #ifdef ENABLE_FAAD case PIANO_AF_AACPLUS: NeAACDecClose(player->aacHandle); free (player->sampleSize); break; #endif /* ENABLE_FAAD */ #ifdef ENABLE_MAD case PIANO_AF_MP3: mad_synth_finish (&player->mp3Synth); mad_frame_finish (&player->mp3Frame); mad_stream_finish (&player->mp3Stream); break; #endif /* ENABLE_MAD */ default: /* this should never happen */ assert (0); break; } if (player->aoError) { ret = (void *) PLAYER_RET_HARDFAIL; } /* Pandora sends broken audio url’s sometimes (“bad request”). ignore them. */ if (wRet != WAITRESS_RET_OK && wRet != WAITRESS_RET_CB_ABORT) { BarUiMsg (player->settings, MSG_ERR, "Cannot access audio file: %s\n", WaitressErrorToStr (wRet)); ret = (void *) PLAYER_RET_SOFTFAIL; } cleanup: ao_close (player->audioOutDevice); WaitressFree (&player->waith); free (player->buffer); player->mode = PLAYER_FINISHED_PLAYBACK; return ret; }
void mp3_mad_free (mp3_info_t *info) { mad_synth_finish (&info->mad_synth); mad_frame_finish (&info->mad_frame); mad_stream_finish (&info->mad_stream); }