summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound
diff options
context:
space:
mode:
author 987123879113 <63495610+987123879113@users.noreply.github.com>2022-04-13 23:36:52 +0900
committer GitHub <noreply@github.com>2022-04-13 16:36:52 +0200
commit232c10aef1d65140fa383930d70463ee9203ca53 (patch)
tree1e2f635d10bbc48a6115b02c26e5afce62212ae4 /src/devices/sound
parentc8ab7240564794057997f285cf38b93fa6f55d7e (diff)
k573dio/k573fpga: Improve counters and status flags (#9554)
Diffstat (limited to 'src/devices/sound')
-rw-r--r--src/devices/sound/mas3507d.cpp88
-rw-r--r--src/devices/sound/mas3507d.h24
2 files changed, 64 insertions, 48 deletions
diff --git a/src/devices/sound/mas3507d.cpp b/src/devices/sound/mas3507d.cpp
index bc4131739cd..23693bfa641 100644
--- a/src/devices/sound/mas3507d.cpp
+++ b/src/devices/sound/mas3507d.cpp
@@ -17,7 +17,7 @@
#define MINIMP3_ONLY_MP3
#define MINIMP3_NO_STDIO
#define MINIMP3_IMPLEMENTATION
-#define MAX_FRAME_SYNC_MATCHES 1
+#define MAX_FRAME_SYNC_MATCHES 3
#include "minimp3/minimp3.h"
#include "minimp3/minimp3_ex.h"
@@ -49,7 +49,7 @@ DEFINE_DEVICE_TYPE(MAS3507D, mas3507d_device, "mas3507d", "Micronas MAS 3507D MP
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)
+ , cb_mpeg_frame_sync(*this), cb_demand(*this)
, i2c_bus_state(IDLE), i2c_bus_address(UNKNOWN), i2c_subdest(UNDEFINED), i2c_command(CMD_BAD)
, i2c_scli(false), i2c_sclo(false), i2c_sdai(false), i2c_sdao(false)
, i2c_bus_curbit(0), i2c_bus_curval(0), i2c_bytecount(0), i2c_io_bank(0), i2c_io_adr(0), i2c_io_count(0), i2c_io_val(0)
@@ -58,9 +58,10 @@ mas3507d_device::mas3507d_device(const machine_config &mconfig, const char *tag,
void mas3507d_device::device_start()
{
- current_rate = 44100; // TODO: related to clock/divider
- stream = stream_alloc(0, 2, current_rate);
- cb_sample.resolve();
+ stream = stream_alloc(0, 2, 44100);
+
+ cb_mpeg_frame_sync.resolve();
+ cb_demand.resolve();
save_item(NAME(mp3data));
save_item(NAME(samples));
@@ -74,8 +75,8 @@ void mas3507d_device::device_start()
save_item(NAME(i2c_sdao));
save_item(NAME(i2c_bus_curbit));
save_item(NAME(i2c_bus_curval));
+
save_item(NAME(mp3data_count));
- save_item(NAME(current_rate));
save_item(NAME(decoded_frame_count));
save_item(NAME(decoded_samples));
save_item(NAME(sample_count));
@@ -90,6 +91,7 @@ void mas3507d_device::device_start()
save_item(NAME(i2c_io_val));
save_item(NAME(i2c_sdao_data));
save_item(NAME(playback_status));
+ save_item(NAME(mp3_is_buffered));
// This should be removed in the future if/when native MP3 decoding is implemented in MAME
save_item(NAME(mp3_dec.mdct_overlap));
@@ -119,6 +121,8 @@ void mas3507d_device::device_reset()
is_muted = false;
gain_ll = gain_rr = 0;
+ stream->set_sample_rate(44100);
+
reset_playback();
}
@@ -355,11 +359,11 @@ void mas3507d_device::i2c_device_got_stop()
LOGOTHER("MAS I2C: got stop\n");
}
-int gain_to_db(double val) {
+int mas3507d_device::gain_to_db(double val) {
return round(20 * log10((0x100000 - val) / 0x80000));
}
-float gain_to_percentage(int val) {
+float mas3507d_device::gain_to_percentage(int val) {
if(val == 0)
return 0; // Special case for muting it seems
@@ -425,30 +429,53 @@ void mas3507d_device::run_program(uint32_t adr)
}
}
+void mas3507d_device::sid_w(uint8_t byte)
+{
+ if (mp3data_count >= mp3data.size()) {
+ std::copy(mp3data.begin() + 1, mp3data.end(), mp3data.begin());
+ mp3data_count--;
+ }
+
+ mp3data[mp3data_count++] = byte;
+
+ if (!mp3_is_buffered) {
+ // Only start the decoder when a full MP3 frame is found
+ int free_format_bytes = 0, frame_size = 0;
+ int frame_offset = mp3d_find_frame(static_cast<const uint8_t *>(&mp3data[0]), mp3data_count, &free_format_bytes, &frame_size);
+ mp3_is_buffered = frame_size && frame_offset + frame_size < mp3data_count;
+ }
+
+ cb_demand(!mp3_is_buffered || mp3data_count < mp3data.size());
+}
+
void mas3507d_device::fill_buffer()
{
- while(mp3data_count + 2 < mp3data.size()) {
- uint16_t v = cb_sample();
- mp3data[mp3data_count++] = v >> 8;
- mp3data[mp3data_count++] = v;
+ cb_mpeg_frame_sync(0);
+
+ if (!mp3_is_buffered) {
+ cb_demand(!mp3_is_buffered || mp3data_count < mp3data.size());
+ return;
}
+ memset(&mp3_info, 0, sizeof(mp3dec_frame_info_t));
sample_count = mp3dec_decode_frame(&mp3_dec, static_cast<const uint8_t *>(&mp3data[0]), mp3data_count, static_cast<mp3d_sample_t *>(&samples[0]), &mp3_info);
samples_idx = 0;
- playback_status = PLAYBACK_STATE_BUFFER_FULL;
- if(sample_count == 0)
+ if (sample_count == 0) {
+ // Frame decode failed
+ reset_playback();
return;
+ }
std::copy(mp3data.begin() + mp3_info.frame_bytes, mp3data.end(), mp3data.begin());
mp3data_count -= mp3_info.frame_bytes;
- if(mp3_info.hz != current_rate) {
- current_rate = mp3_info.hz;
- stream->set_sample_rate(current_rate);
- }
+ stream->set_sample_rate(mp3_info.hz);
decoded_frame_count++;
+ cb_mpeg_frame_sync(1);
+
+ cb_demand(!mp3_is_buffered || mp3data_count < mp3data.size());
}
void mas3507d_device::append_buffer(std::vector<write_stream_view> &outputs, int &pos, int scount)
@@ -459,8 +486,6 @@ void mas3507d_device::append_buffer(std::vector<write_stream_view> &outputs, int
if(s1 > sample_count)
s1 = sample_count;
- playback_status = PLAYBACK_STATE_DEMAND_BUFFER;
-
for(int i = 0; i < s1; i++) {
outputs[0].put_int(pos, samples[samples_idx * bytes_per_sample], 32768);
outputs[1].put_int(pos, samples[samples_idx * bytes_per_sample + (bytes_per_sample >> 1)], 32768);
@@ -478,22 +503,20 @@ void mas3507d_device::append_buffer(std::vector<write_stream_view> &outputs, int
void mas3507d_device::reset_playback()
{
+ if (mp3data_count != 0)
+ std::fill(mp3data.begin(), mp3data.end(), 0);
+
+ if (sample_count != 0 || decoded_samples != 0)
+ std::fill(samples.begin(), samples.end(), 0);
+
mp3dec_init(&mp3_dec);
mp3data_count = 0;
sample_count = 0;
decoded_frame_count = 0;
decoded_samples = 0;
- playback_status = PLAYBACK_STATE_IDLE;
- is_started = false;
samples_idx = 0;
- std::fill(mp3data.begin(), mp3data.end(), 0);
- std::fill(samples.begin(), samples.end(), 0);
-}
-void mas3507d_device::start_playback()
-{
- reset_playback();
- is_started = true;
+ mp3_is_buffered = false;
}
void mas3507d_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
@@ -502,13 +525,10 @@ void mas3507d_device::sound_stream_update(sound_stream &stream, std::vector<read
int pos = 0;
while(pos < csamples) {
- if(is_started && sample_count == 0)
+ if(sample_count == 0)
fill_buffer();
- if(!is_started || sample_count <= 0) {
- playback_status = PLAYBACK_STATE_IDLE;
- decoded_frame_count = 0;
- decoded_samples = 0;
+ if(sample_count <= 0) {
outputs[0].fill(0, pos);
outputs[1].fill(0, pos);
return;
diff --git a/src/devices/sound/mas3507d.h b/src/devices/sound/mas3507d.h
index 36f95de72db..52c2e924109 100644
--- a/src/devices/sound/mas3507d.h
+++ b/src/devices/sound/mas3507d.h
@@ -12,31 +12,22 @@
class mas3507d_device : public device_t, public device_sound_interface
{
public:
- enum {
- PLAYBACK_STATE_IDLE,
- PLAYBACK_STATE_BUFFER_FULL,
- PLAYBACK_STATE_DEMAND_BUFFER
- };
-
// construction/destruction
mas3507d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- auto sample_cb() { return cb_sample.bind(); }
+ auto mpeg_frame_sync_cb() { return cb_mpeg_frame_sync.bind(); }
+ auto demand_cb() { return cb_demand.bind(); }
int i2c_scl_r();
int i2c_sda_r();
void i2c_scl_w(bool line);
void i2c_sda_w(bool line);
- uint32_t get_samples() const { return decoded_samples; }
- uint32_t get_status() const { return playback_status; }
+ void sid_w(uint8_t byte);
void update_stream() { stream->update(); }
void reset_playback();
- void start_playback();
-
- bool is_started;
protected:
virtual void device_start() override;
@@ -56,7 +47,11 @@ private:
void fill_buffer();
void append_buffer(std::vector<write_stream_view> &outputs, int &pos, int scount);
- devcb_read16 cb_sample;
+ int gain_to_db(double val);
+ float gain_to_percentage(int val);
+
+ devcb_write_line cb_mpeg_frame_sync;
+ devcb_write_line cb_demand;
enum {
CMD_DEV_WRITE = 0x3a,
@@ -92,7 +87,8 @@ private:
uint32_t i2c_io_bank, i2c_io_adr, i2c_io_count, i2c_io_val;
uint32_t i2c_sdao_data;
- uint32_t mp3data_count, current_rate;
+ bool mp3_is_buffered;
+ uint32_t mp3data_count;
uint32_t decoded_frame_count, decoded_samples;
int32_t sample_count, samples_idx;