diff options
Diffstat (limited to 'src/devices/sound/mas3507d.cpp')
-rw-r--r-- | src/devices/sound/mas3507d.cpp | 112 |
1 files changed, 101 insertions, 11 deletions
diff --git a/src/devices/sound/mas3507d.cpp b/src/devices/sound/mas3507d.cpp index 519136cfb4c..cd04e163c6b 100644 --- a/src/devices/sound/mas3507d.cpp +++ b/src/devices/sound/mas3507d.cpp @@ -7,20 +7,31 @@ #include "emu.h" #include "mas3507d.h" +#define MINIMP3_ONLY_MP3 +#define MINIMP3_NO_STDIO +#define MINIMP3_IMPLEMENTATION +#define MAX_FRAME_SYNC_MATCHES 1 +#include "minimp3/minimp3.h" +#include "minimp3/minimp3_ex.h" + // device type definition DEFINE_DEVICE_TYPE(MAS3507D, mas3507d_device, "mas3507d", "MAS 3507D MPEG decoder") mas3507d_device::mas3507d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, MAS3507D, tag, owner, clock) , device_sound_interface(mconfig, *this) + , cb_sample(*this) , i2c_bus_state(), i2c_bus_address(), i2c_scli(false), i2c_sclo(false), i2c_sdai(false), i2c_sdao(false) , i2c_bus_curbit(0), i2c_bus_curval(0), i2c_subdest(), i2c_command(), i2c_bytecount(0), i2c_io_bank(0), i2c_io_adr(0), i2c_io_count(0), i2c_io_val(0) - , m_samples(nullptr) { } void mas3507d_device::device_start() { + current_rate = 44100; + stream = stream_alloc(0, 2, current_rate); + mp3dec_init(&mp3_dec); + cb_sample.resolve(); } void mas3507d_device::device_reset() @@ -31,6 +42,7 @@ void mas3507d_device::device_reset() i2c_bus_address = UNKNOWN; i2c_bus_curbit = -1; i2c_bus_curval = 0; + total_sample_count = 0; } void mas3507d_device::i2c_scl_w(bool line) @@ -272,11 +284,6 @@ void mas3507d_device::mem_write(int bank, uint32_t adr, uint32_t val) case 0x0032f: logerror("MAS3507D: OutputConfig = %05x\n", val); break; case 0x107f8: logerror("MAS3507D: left->left gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val)); - - if (m_samples != nullptr) { - m_samples->set_volume(0, gain_to_percentage(val)); - } - break; case 0x107f9: logerror("MAS3507D: left->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val)); @@ -286,11 +293,6 @@ void mas3507d_device::mem_write(int bank, uint32_t adr, uint32_t val) break; case 0x107fb: logerror("MAS3507D: right->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val)); - - if (m_samples != nullptr) { - m_samples->set_volume(1, gain_to_percentage(val)); - } - break; default: logerror("MAS3507D: %d:%04x = %05x\n", bank, adr, val); break; } @@ -317,6 +319,94 @@ void mas3507d_device::run_program(uint32_t adr) } } +void mas3507d_device::fill_buffer() +{ + while(mp3_count < mp3data.size()) { + u16 v = cb_sample(); + mp3data[mp3_count++] = v >> 8; + mp3data[mp3_count++] = v; + } + + int scount = mp3dec_decode_frame(&mp3_dec, mp3data.begin(), mp3_count, samples.begin(), &mp3_info); + + if(!scount) { + int to_drop = mp3_info.frame_bytes; + // At 1MHz, we can transfer around 2082 bytes/video frame. So + // that puts a boundary on how much we're ready to drop + if(to_drop > 2082 || !to_drop) + to_drop = 2082; + std::copy(mp3data.begin() + to_drop, mp3data.end(), mp3data.begin()); + mp3_count -= to_drop; + return; + } + + std::copy(mp3data.begin() + mp3_info.frame_bytes, mp3data.end(), mp3data.begin()); + mp3_count -= mp3_info.frame_bytes; + + if(mp3_info.channels == 1) + sample_count = scount; + else + sample_count = scount; + + if(mp3_info.hz != current_rate) { + current_rate = mp3_info.hz; + stream->set_sample_rate(current_rate); + } +} + +void mas3507d_device::append_buffer(stream_sample_t **outputs, int &pos, int scount) +{ + if(!sample_count) + return; + + int s1 = scount - pos; + if(s1 > sample_count) + s1 = sample_count; + + if(mp3_info.channels == 1) { + for(int i=0; i<s1; i++) { + stream_sample_t v = samples[i]; + outputs[0][i+pos] = v; + outputs[1][i+pos] = v; + } + } else { + for(int i=0; i<s1; i++) { + outputs[0][i+pos] = samples[i*2]; + outputs[1][i+pos] = samples[i*2+1]; + } + } + + if(s1 == sample_count) { + pos += s1; + sample_count = 0; + return; + } + + if(mp3_info.channels == 1) + std::copy(samples.begin() + s1, samples.begin() + sample_count, samples.begin()); + else + std::copy(samples.begin() + s1*2, samples.begin() + sample_count*2, samples.begin()); + + pos += s1; + sample_count -= s1; +} + void mas3507d_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { + int pos = 0; + total_sample_count += samples; + append_buffer(outputs, pos, samples); + for(;;) { + if(pos == samples) + return; + fill_buffer(); + if(!sample_count) { + for(int i=pos; i != samples; i++) { + outputs[0][i] = 0; + outputs[1][i] = 0; + } + return; + } + append_buffer(outputs, pos, samples); + } } |