📄 libmadplugin.cpp
字号:
bool LibMadPlugin::close() { debugMsg( "LibMadPlugin::close" ); int result = TRUE; mad_synth_finish(&d->synth); mad_frame_finish(&d->frame); mad_stream_finish(&d->stream);#if defined(HAVE_MMAP) if (d->input.fdm) { if (unmap_file(d->input.fdm, d->input.length) == -1) { qDebug("error munmapping file"); result = FALSE; } d->input.fdm = 0; d->input.data = 0; }#endif if (d->input.data) { free(d->input.data); d->input.data = 0; } if (::close(d->input.fd) == -1) { qDebug("error closing file %s", d->input.path); result = FALSE; } d->input.fd = 0; return result;}/*! \internal */bool LibMadPlugin::isOpen() { debugMsg( "LibMadPlugin::isOpen" ); return ( d->input.fd != 0 );}/*! \internal */int LibMadPlugin::audioStreams() { debugMsg( "LibMadPlugin::audioStreams" ); return 1;}/*! \internal */int LibMadPlugin::audioChannels( int ) { debugMsg( "LibMadPlugin::audioChannels" );/* long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 ); return d->frame.header.mode > 0 ? 2 : 1;*/ return 2;}/*! \internal */int LibMadPlugin::audioFrequency( int ) { debugMsg( "LibMadPlugin::audioFrequency" );#ifdef OLD_MEDIAPLAYER_API long t; short t1[5]; audioReadStereoSamples( t1, 1, t, 0 );#else long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );#endif// qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate ); return d->frame.header.samplerate;}/*! \internal */int LibMadPlugin::audioSamples( int ) { debugMsg( "LibMadPlugin::audioSamples" ); long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream );/* qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds, d->frame.header.samplerate ); return d->frame.header.duration.seconds * d->frame.header.samplerate;*/ if ( d->frame.header.bitrate == 0 ) return 0; int samples = (d->input.fileLength / (d->frame.header.bitrate/8)) * d->frame.header.samplerate; qDebug( "LibMadPlugin::audioSamples: %i * %i * 8 / %i", (int)d->input.fileLength, (int)d->frame.header.samplerate, (int)d->frame.header.bitrate ); qDebug( "LibMadPlugin::audioSamples: %i", samples ); return samples;}/*! \internal \a pos*/bool LibMadPlugin::audioSetSample( long pos, int ) { debugMsg( "LibMadPlugin::audioSetSample" ); long totalSamples = audioSamples(0); if ( totalSamples <= 1 ) return FALSE; // Seek to requested position qDebug( "seek pos: %i", (int)((double)pos * d->input.fileLength / totalSamples) ); ::lseek( d->input.fd, (long)((double)pos * d->input.fileLength / totalSamples), SEEK_SET ); mad_stream_sync(&d->stream); mad_stream_init(&d->stream); mad_frame_init(&d->frame); mad_synth_init(&d->synth); d->buffered = 0; d->resync = TRUE; return TRUE;}/*! \internal */long LibMadPlugin::audioGetSample( int ) { debugMsg( "LibMadPlugin::audioGetSample" ); return 0;}#ifdef OLD_MEDIAPLAYER_API/*! \internal*/bool LibMadPlugin::audioReadSamples( short *, int, long, int ) { debugMsg( "LibMadPlugin::audioReadSamples" ); return FALSE;}/*! \internal */bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) { debugMsg( "LibMadPlugin::audioReReadSamples" ); return FALSE;}#endif/*! \internal */bool LibMadPlugin::read() { debugMsg( "LibMadPlugin::read" ); int len; if (d->input.eof) return FALSE;#if defined(HAVE_MMAP) if (d->input.fdm) { unsigned long skip = 0; if (d->stream.next_frame) { struct stat stat; if (fstat(d->input.fd, &stat) == -1) return FALSE; if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) return FALSE; // file size changed; update memory map skip = d->stream.next_frame - d->input.data; if (unmap_file(d->input.fdm, d->input.length) == -1) { d->input.fdm = 0; d->input.data = 0; return FALSE; } d->input.length = stat.st_size; d->input.fdm = map_file(d->input.fd, &d->input.length); if (d->input.fdm == 0) { d->input.data = 0; return FALSE; } d->input.data = (unsigned char *)d->input.fdm; } mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); } else#endif { if (d->stream.next_frame) { if ( d->stream.next_frame > &d->input.data[d->input.length] ) d->input.length = 0; else d->input.length = &d->input.data[d->input.length] - d->stream.next_frame; memmove(d->input.data, d->stream.next_frame, d->input.length); } if ( d->resync ) { d->input.length = 0; d->resync = FALSE; } do { len = ::read(d->input.fd, d->input.data + d->input.length, MPEG_BUFFER_SIZE - d->input.length); } while (len == -1 && errno == EINTR); if (len == -1) { qDebug("error reading audio"); return FALSE; } else if (len == 0) { d->input.eof = 1; } mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); } return TRUE;}static inline signed int scale( mad_fixed_t sample ){ sample += (1L << (MAD_F_FRACBITS - 16)); sample = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample ); return sample >> (MAD_F_FRACBITS + 1 - 16);}inline void audio_pcm( unsigned short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ){ if ( right ) { while (nsamples--) { *data++ = scale( *left++ ); *data++ = scale( *right++ ); } } else { while (nsamples--) { signed int mono = scale( *left++ ); *data++ = mono; *data++ = mono; } }}/*! \a output \a samples \a samplesMade \internal */bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) { debugMsg( "LibMadPlugin::decode" ); static const int maxBuffered = 8000; // 65536; samplesMade = 0; if ( !isOpen() ) return FALSE; if ( samples > maxBuffered ) samples = maxBuffered; int offset = d->buffered; while ( d->buffered < maxBuffered ) { while (mad_frame_decode(&d->frame, &d->stream) == -1) { if ( d->stream.error == MAD_ERROR_BUFLEN ) { debugMsg( "feed me" ); // No tr qDebug( "feed me" ); return FALSE; // Feed me } if ( d->stream.error == MAD_ERROR_BADCRC ) { mad_frame_mute(&d->frame); qDebug( "error decoding, bad crc" ); } } mad_synth_frame(&d->synth, &d->frame); int decodedSamples = d->synth.pcm.length; memcpy( &(d->buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) ); if ( d->synth.pcm.channels == 2 ) memcpy( &(d->buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) ); offset += decodedSamples; d->buffered += decodedSamples; } if ( samples >= d->buffered ) samples = d->buffered; audio_pcm( (unsigned short*)output, samples, d->buffer[0], (d->synth.pcm.channels == 2) ? d->buffer[1] : 0 ); samplesMade = samples; d->buffered -= samples; memmove( d->buffer[0], &(d->buffer[0][samples]), d->buffered * sizeof(mad_fixed_t) ); if ( d->synth.pcm.channels == 2 ) memmove( d->buffer[1], &(d->buffer[1][samples]), d->buffered * sizeof(mad_fixed_t) ); return TRUE;}#ifdef OLD_MEDIAPLAYER_APIbool LibMadPlugin::audioReadMonoSamples( short *, long, long&, int ) { debugMsg( "LibMadPlugin::audioReadMonoSamples" ); return FALSE;}bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {#else/*! \internal*/bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) {#endif debugMsg( "LibMadPlugin::audioReadStereoSamples" ); static bool needInput = TRUE; if ( !isOpen() ) return FALSE; if ( samples == 0 ) return TRUE; if ( d->resync || needInput ) { if ( d->input.eof ) { samplesMade = samples; memset( output, 0, samples ); return FALSE; } qDebug("getting more input"); if ( !read() ) { qDebug("failed getting more input"); if ( !d->input.eof ) { // Perhaps a timeout happened or some error // return 0 samples read but keep needInput flag as TRUE // so it retrys reading next time samplesMade = 0; qDebug("ret a - couldn't get more input"); return TRUE; } } needInput = FALSE; } if ( !decode( output, samples, samplesMade ) ) // Need more input to decode needInput = TRUE; return TRUE;}/*! \internal */double LibMadPlugin::getTime() { debugMsg( "LibMadPlugin::getTime" ); return 0.0;}// QDOC_SKIP_END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -