Compare commits
2 commits
6e8538c7c9
...
fc2a14b0fa
Author | SHA1 | Date | |
---|---|---|---|
|
fc2a14b0fa | ||
|
410395dded |
2 changed files with 17 additions and 11 deletions
|
@ -15,12 +15,11 @@
|
||||||
|
|
||||||
#import "Plugin.h"
|
#import "Plugin.h"
|
||||||
|
|
||||||
#define INPUT_BUFFER_SIZE 5 * 8192
|
#define INPUT_BUFFER_SIZE 16 * 1024
|
||||||
|
|
||||||
@interface MP3Decoder : NSObject <CogDecoder> {
|
@interface MP3Decoder : NSObject <CogDecoder> {
|
||||||
BOOL seekable;
|
BOOL seekable;
|
||||||
mp3dec_t _decoder;
|
unsigned char _decoder_buffer[INPUT_BUFFER_SIZE];
|
||||||
unsigned char _decoder_buffer[32768];
|
|
||||||
size_t _decoder_buffer_filled;
|
size_t _decoder_buffer_filled;
|
||||||
|
|
||||||
mp3dec_ex_t _decoder_ex;
|
mp3dec_ex_t _decoder_ex;
|
||||||
|
|
|
@ -38,6 +38,8 @@ static int mp3_seek_callback(uint64_t position, void *user_data) {
|
||||||
size_t id3_length = 0;
|
size_t id3_length = 0;
|
||||||
|
|
||||||
if(seekable) {
|
if(seekable) {
|
||||||
|
// minimp3 already skips ID3v2, but we need to supplement it with support for
|
||||||
|
// iTunes gapless info, which is stored in the ID3v2 tag
|
||||||
uint8_t buffer[10];
|
uint8_t buffer[10];
|
||||||
size_t buflen = [source read:&buffer[0] amount:10];
|
size_t buflen = [source read:&buffer[0] amount:10];
|
||||||
|
|
||||||
|
@ -137,12 +139,14 @@ static int mp3_seek_callback(uint64_t position, void *user_data) {
|
||||||
if(error)
|
if(error)
|
||||||
return NO;
|
return NO;
|
||||||
if(_foundiTunSMPB) {
|
if(_foundiTunSMPB) {
|
||||||
|
// start_delay is used for seeking, to_skip must be filled for the first packet decoded
|
||||||
|
// and detected_samples will truncate the end padding
|
||||||
_decoder_ex.start_delay = _decoder_ex.to_skip = _startPadding * _decoder_ex.info.channels;
|
_decoder_ex.start_delay = _decoder_ex.to_skip = _startPadding * _decoder_ex.info.channels;
|
||||||
_decoder_ex.detected_samples = totalFrames * _decoder_ex.info.channels;
|
_decoder_ex.detected_samples = totalFrames * _decoder_ex.info.channels;
|
||||||
_decoder_ex.samples = (totalFrames + _startPadding + _endPadding) * _decoder_ex.info.channels;
|
_decoder_ex.samples = (totalFrames + _startPadding + _endPadding) * _decoder_ex.info.channels;
|
||||||
}
|
}
|
||||||
mp3d_sample_t *sample_ptr = NULL;
|
mp3d_sample_t *sample_ptr = NULL;
|
||||||
size_t samples = mp3dec_ex_read_frame(&_decoder_ex, &sample_ptr, &_decoder_info, 1152 * 2);
|
size_t samples = mp3dec_ex_read_frame(&_decoder_ex, &sample_ptr, &_decoder_info, MINIMP3_MAX_SAMPLES_PER_FRAME);
|
||||||
if(samples && sample_ptr) {
|
if(samples && sample_ptr) {
|
||||||
samples_filled = samples / _decoder_info.channels;
|
samples_filled = samples / _decoder_info.channels;
|
||||||
memcpy(&_decoder_buffer_output[0], sample_ptr, sizeof(mp3d_sample_t) * samples);
|
memcpy(&_decoder_buffer_output[0], sample_ptr, sizeof(mp3d_sample_t) * samples);
|
||||||
|
@ -157,10 +161,10 @@ static int mp3_seek_callback(uint64_t position, void *user_data) {
|
||||||
}
|
}
|
||||||
bitrate = (double)((_fileSize - id3_length) * 8) / ((double)totalFrames / (double)_decoder_info.hz) / 1000.0;
|
bitrate = (double)((_fileSize - id3_length) * 8) / ((double)totalFrames / (double)_decoder_info.hz) / 1000.0;
|
||||||
} else {
|
} else {
|
||||||
_decoder_buffer_filled = [source read:_decoder_buffer amount:32768];
|
_decoder_buffer_filled = [source read:_decoder_buffer amount:INPUT_BUFFER_SIZE];
|
||||||
inputEOF = _decoder_buffer_filled < 32768;
|
inputEOF = _decoder_buffer_filled < INPUT_BUFFER_SIZE;
|
||||||
mp3dec_init(&_decoder);
|
mp3dec_init(&_decoder_ex.mp3d);
|
||||||
int samples = mp3dec_decode_frame(&_decoder, _decoder_buffer, (int)_decoder_buffer_filled, &_decoder_buffer_output[0], &_decoder_info);
|
int samples = mp3dec_decode_frame(&_decoder_ex.mp3d, _decoder_buffer, (int)_decoder_buffer_filled, &_decoder_buffer_output[0], &_decoder_info);
|
||||||
if(!samples)
|
if(!samples)
|
||||||
return NO;
|
return NO;
|
||||||
size_t bytes_read = _decoder_info.frame_bytes;
|
size_t bytes_read = _decoder_info.frame_bytes;
|
||||||
|
@ -231,7 +235,7 @@ static int mp3_seek_callback(uint64_t position, void *user_data) {
|
||||||
|
|
||||||
if(seekable) {
|
if(seekable) {
|
||||||
mp3d_sample_t *sample_ptr = NULL;
|
mp3d_sample_t *sample_ptr = NULL;
|
||||||
size_t samples = mp3dec_ex_read_frame(&_decoder_ex, &sample_ptr, &_decoder_info, 1152 * 2);
|
size_t samples = mp3dec_ex_read_frame(&_decoder_ex, &sample_ptr, &_decoder_info, MINIMP3_MAX_SAMPLES_PER_FRAME);
|
||||||
if(samples && sample_ptr) {
|
if(samples && sample_ptr) {
|
||||||
samples_filled = samples / _decoder_info.channels;
|
samples_filled = samples / _decoder_info.channels;
|
||||||
memcpy(&_decoder_buffer_output[0], sample_ptr, sizeof(mp3d_sample_t) * samples);
|
memcpy(&_decoder_buffer_output[0], sample_ptr, sizeof(mp3d_sample_t) * samples);
|
||||||
|
@ -239,7 +243,7 @@ static int mp3_seek_callback(uint64_t position, void *user_data) {
|
||||||
inputEOF = YES;
|
inputEOF = YES;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size_t bytesRemain = 32768 - _decoder_buffer_filled;
|
size_t bytesRemain = INPUT_BUFFER_SIZE - _decoder_buffer_filled;
|
||||||
ssize_t bytesRead = [_source read:&_decoder_buffer[_decoder_buffer_filled] amount:bytesRemain];
|
ssize_t bytesRead = [_source read:&_decoder_buffer[_decoder_buffer_filled] amount:bytesRemain];
|
||||||
if(bytesRead < 0 || bytesRead < bytesRemain) {
|
if(bytesRead < 0 || bytesRead < bytesRemain) {
|
||||||
inputEOF = YES;
|
inputEOF = YES;
|
||||||
|
@ -247,7 +251,7 @@ static int mp3_seek_callback(uint64_t position, void *user_data) {
|
||||||
if(bytesRead > 0) {
|
if(bytesRead > 0) {
|
||||||
_decoder_buffer_filled += bytesRead;
|
_decoder_buffer_filled += bytesRead;
|
||||||
}
|
}
|
||||||
int samples = mp3dec_decode_frame(&_decoder, &_decoder_buffer[0], (int)_decoder_buffer_filled, &_decoder_buffer_output[0], &_decoder_info);
|
int samples = mp3dec_decode_frame(&_decoder_ex.mp3d, &_decoder_buffer[0], (int)_decoder_buffer_filled, &_decoder_buffer_output[0], &_decoder_info);
|
||||||
if(samples > 0) {
|
if(samples > 0) {
|
||||||
samples_filled = samples;
|
samples_filled = samples;
|
||||||
} else {
|
} else {
|
||||||
|
@ -272,6 +276,9 @@ static int mp3_seek_callback(uint64_t position, void *user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)close {
|
- (void)close {
|
||||||
|
if(seekable) {
|
||||||
|
mp3dec_ex_close(&_decoder_ex);
|
||||||
|
}
|
||||||
if(_source) {
|
if(_source) {
|
||||||
_source = nil;
|
_source = nil;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue