diff --git a/src/emu/bus/ti99_peb/bwg.c b/src/emu/bus/ti99_peb/bwg.c index d5504ff2283..55a1150f972 100644 --- a/src/emu/bus/ti99_peb/bwg.c +++ b/src/emu/bus/ti99_peb/bwg.c @@ -670,9 +670,13 @@ MACHINE_CONFIG_FRAGMENT( bwg_fdc ) MCFG_MM58274C_DAY1(0) // sunday MCFG_FLOPPY_DRIVE_ADD("0", bwg_floppies, "525dd", snug_bwg_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("1", bwg_floppies, "525dd", snug_bwg_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("2", bwg_floppies, NULL, snug_bwg_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("3", bwg_floppies, NULL, snug_bwg_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MACHINE_CONFIG_END ROM_START( bwg_fdc ) diff --git a/src/emu/bus/ti99_peb/hfdc.c b/src/emu/bus/ti99_peb/hfdc.c index 5bbac318b6c..188cfed82e2 100644 --- a/src/emu/bus/ti99_peb/hfdc.c +++ b/src/emu/bus/ti99_peb/hfdc.c @@ -1027,9 +1027,13 @@ MACHINE_CONFIG_FRAGMENT( ti99_hfdc ) MCFG_HDC92X4_DMA_OUT_CALLBACK(WRITE8(myarc_hfdc_device, write_buffer)) MCFG_FLOPPY_DRIVE_ADD("f1", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("f2", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("f3", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("f4", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) // NB: Hard disks don't go without image (other than floppy drives) MCFG_MFM_HARDDISK_CONN_ADD("h1", hfdc_harddisks, NULL, MFM_BYTE, 3000, 20, MFMHD_GEN_FORMAT) diff --git a/src/emu/bus/ti99_peb/ti_fdc.c b/src/emu/bus/ti99_peb/ti_fdc.c index 610832e2539..e43a1be2475 100644 --- a/src/emu/bus/ti99_peb/ti_fdc.c +++ b/src/emu/bus/ti99_peb/ti_fdc.c @@ -407,8 +407,11 @@ MACHINE_CONFIG_FRAGMENT( ti_fdc ) MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(ti_fdc_device, fdc_irq_w)) MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(ti_fdc_device, fdc_drq_w)) MCFG_FLOPPY_DRIVE_ADD("0", tifdc_floppies, "525dd", ti_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("1", tifdc_floppies, "525dd", ti_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("2", tifdc_floppies, NULL, ti_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MACHINE_CONFIG_END ROM_START( ti_fdc ) diff --git a/src/emu/imagedev/floppy.c b/src/emu/imagedev/floppy.c index c4a61514b89..f2c3773bc3e 100644 --- a/src/emu/imagedev/floppy.c +++ b/src/emu/imagedev/floppy.c @@ -18,7 +18,9 @@ */ // Show step operation -#define TRACE_STEP 0 +#define TRACE_STEP 1 + +#define FLOPSND_TAG "floppysound" // device type definition const device_type FLOPPY_CONNECTOR = &device_creator; @@ -123,7 +125,8 @@ const floppy_format_type floppy_image_device::default_floppy_formats[] = { floppy_connector::floppy_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, FLOPPY_CONNECTOR, "Floppy drive connector abstraction", tag, owner, clock, "floppy_connector", __FILE__), - device_slot_interface(mconfig, *this) + device_slot_interface(mconfig, *this), + m_enable_sound(false) { } @@ -144,7 +147,10 @@ void floppy_connector::device_config_complete() { floppy_image_device *dev = dynamic_cast(get_card_device()); if(dev) + { dev->set_formats(formats); + dev->enable_sound(m_enable_sound); + } } floppy_image_device *floppy_connector::get_device() @@ -161,7 +167,8 @@ floppy_image_device::floppy_image_device(const machine_config &mconfig, device_t device_image_interface(mconfig, *this), device_slot_card_interface(mconfig, *this), image(NULL), - fif_list(NULL) + fif_list(NULL), + m_make_sound(false) { extension_list[0] = '\0'; m_err = IMAGE_ERROR_INVALIDIMAGE; @@ -304,12 +311,20 @@ void floppy_image_device::device_start() setup_characteristics(); + if (m_make_sound) m_sound_out = subdevice(FLOPSND_TAG); + save_item(NAME(cyl)); save_item(NAME(subcyl)); } void floppy_image_device::device_reset() { + if (m_make_sound) + { + // Have we loaded all samples? Otherwise mute the floppy. + m_make_sound = m_sound_out->samples_loaded(); + } + revolution_start_time = attotime::never; revolution_count = 0; mon = 1; @@ -358,6 +373,7 @@ floppy_image_format_t *floppy_image_device::identify(std::string filename) bool floppy_image_device::call_load() { io_generic io; + // Do _not_ remove this cast otherwise the pointer will be incorrect when used by the ioprocs. io.file = (device_image_interface *)this; io.procs = &image_ioprocs; @@ -490,6 +506,8 @@ void floppy_image_device::mon_w(int state) cur_ready_cb(this, ready); } } + + if (m_make_sound) m_sound_out->motor(state==0); } attotime floppy_image_device::time_next_index() @@ -581,6 +599,8 @@ void floppy_image_device::stp_w(int state) } } subcyl = 0; + // Do we want a stepper sound? + if (m_make_sound) m_sound_out->step(state==0); } } @@ -1032,6 +1052,148 @@ void ui_menu_control_floppy_image::handle() } } +//=================================================================== +// Floppy sound +// +// In order to enable floppy sound you must add the line +// MCFG_FLOPPY_DRIVE_SOUND(true) +// after MCFG_FLOPPY_DRIVE_ADD +// and you must put audio samples (44100Hz, mono) with names as +// shown in floppy_sample_names into the directory samples/floppy +// Sound will be disabled when these samples are missing. +// +// MZ, Aug 2015 +//=================================================================== + +floppy_sound_device::floppy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : samples_device(mconfig, FLOPPYSOUND, "Floppy sound", tag, owner, clock, "flopsnd", __FILE__) +{ + m_motor = false; + m_step = false; + m_loaded = false; +} + +void floppy_sound_device::device_start() +{ + // Read audio samples. The samples are stored in the list m_samples. + m_loaded = load_samples(); + + // The per-floppy stream. If we don't have all samples, don't allocate a stream. + if (m_loaded) m_sound = machine().sound().stream_alloc(*this, 0, 1, clock()); + + // Of course, we can read the length from the sample_t, but we want to + // be able to fine-tune it, for instance, choose different start and end points + m_samplestart_motor = 0; + m_sampleend_motor = 8820; // 200ms + m_samplestart_step = 0; + m_sampleend_step = 2205; // 50ms + + // Mintime says how long the sound persists after the initiating signal + // is cleared (important for short step pulses) + m_motor_mintime = 8820; + m_step_mintime = 1500; + + // Number of updates until the sample stops + m_motor_time = 0; + m_step_time = 0; + + // Initialize position + m_samplepos_step = m_samplestart_step; + m_samplepos_motor = m_samplestart_motor; +} + +void floppy_sound_device::motor(bool state) +{ + m_sound->update(); + // We do not reset the motor sample on state==true because we don't want + // the sound to "jump" + if (state==true) m_motor_time = m_motor_mintime; + m_motor = state; +} + +void floppy_sound_device::step(bool state) +{ + m_sound->update(); // required + if (state==true) + { + m_step_time = m_step_mintime; + m_samplepos_step = m_samplestart_step; + } + m_step = state; +} + +//------------------------------------------------- +// sound_stream_update - update the sound stream +//------------------------------------------------- + +void floppy_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + // We are using only one stream, unlike the parent class + // Also, there is no need for interpolation, as we only expect + // one sample rate of 44100 for all samples + + INT16 out = 0; + + stream_sample_t *samplebuffer = outputs[0]; + sample_t& motor_sample = m_sample[0]; + sample_t& step_sample = m_sample[1]; + + while (samples-- > 0) + { + // Motor sound + if (m_motor_time > 0) + { + if (m_samplepos_motor < m_sampleend_motor) + // Stream value + out = motor_sample.data[m_samplepos_motor++]; + else + m_samplepos_motor = m_samplestart_motor; + + // When the motor is turned off, count down the samples + if (!m_motor) m_motor_time--; + } + + // Stepper sound + if (m_step_time > 0) + { + if (m_samplepos_step < m_sampleend_step) + // Mix it into the stream value + out = out + step_sample.data[m_samplepos_step++]; + else + m_samplepos_step = m_samplestart_step; + + // When the step is turned off, count down the samples + if (!m_step) m_step_time--; + } + // Write to the stream buffer + *(samplebuffer++) = out; + } +} + +static const char *const floppy_sample_names[] = +{ + "*floppy", + "flop_35_motor", + "flop_35_step", + 0 +}; + +#define FLOPSPK "flopsndout" + +MACHINE_CONFIG_FRAGMENT( floppy_img ) + MCFG_SPEAKER_STANDARD_MONO(FLOPSPK) + MCFG_SOUND_ADD(FLOPSND_TAG, FLOPPYSOUND, 44100) + MCFG_SAMPLES_NAMES(floppy_sample_names) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, FLOPSPK, 0.75) +MACHINE_CONFIG_END + +machine_config_constructor floppy_image_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( floppy_img ); +} + +const device_type FLOPPYSOUND = &device_creator; + //************************************************************************** // GENERIC FLOPPY DRIVE DEFINITIONS diff --git a/src/emu/imagedev/floppy.h b/src/emu/imagedev/floppy.h index 5b230ae9e49..7084f7e4e08 100644 --- a/src/emu/imagedev/floppy.h +++ b/src/emu/imagedev/floppy.h @@ -20,12 +20,16 @@ #include "formats/cqm_dsk.h" #include "formats/dsk_dsk.h" #include "ui/imgcntrl.h" +#include "sound/samples.h" #define MCFG_FLOPPY_DRIVE_ADD(_tag, _slot_intf, _def_slot, _formats) \ MCFG_DEVICE_ADD(_tag, FLOPPY_CONNECTOR, 0) \ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \ static_cast(device)->set_formats(_formats); +#define MCFG_FLOPPY_DRIVE_SOUND(_doit) \ + static_cast(device)->enable_sound(_doit); + #define DECLARE_FLOPPY_FORMATS(_name) \ static const floppy_format_type _name [] @@ -44,6 +48,7 @@ FLOPPY_DSK_FORMAT, \ NULL }; +class floppy_sound_device; /*************************************************************************** TYPE DEFINITIONS @@ -129,6 +134,9 @@ public: static const floppy_format_type default_floppy_formats[]; + // Enable sound + void enable_sound(bool doit) { m_make_sound = doit; } + protected: // device-level overrides virtual void device_config_complete(); @@ -136,6 +144,8 @@ protected: virtual void device_reset(); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual machine_config_constructor device_mconfig_additions() const; + virtual void setup_characteristics() = 0; floppy_image_format_t *input_format; @@ -187,6 +197,10 @@ protected: void write_zone(UINT32 *buf, int &cells, int &index, UINT32 spos, UINT32 epos, UINT32 mg); void commit_image(); attotime get_next_index_time(std::vector &buf, int index, int delta, attotime base); + + // Sound + bool m_make_sound; + floppy_sound_device* m_sound_out; }; class ui_menu_control_floppy_image : public ui_menu_control_device_image { @@ -249,6 +263,43 @@ DECLARE_FLOPPY_IMAGE_DEVICE(teac_fd_55f, "floppy_5_25") DECLARE_FLOPPY_IMAGE_DEVICE(teac_fd_55g, "floppy_5_25") DECLARE_FLOPPY_IMAGE_DEVICE(alps_3255190x, "floppy_5_25") +extern const device_type FLOPPYSOUND; + +/* + Floppy drive sound +*/ +class floppy_sound_device : public samples_device +{ +public: + floppy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void motor(bool on); + void step(bool on); + bool samples_loaded() { return m_loaded; } + +protected: + void device_start(); + +private: + // device_sound_interface overrides + void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); + + sound_stream* m_sound; + bool m_loaded; + + int m_sampleend_motor; + int m_samplepos_motor; + int m_samplestart_motor; + int m_motor_mintime; // min time for the samples; sound persists for that time + int m_motor_time; + bool m_motor; + + int m_sampleend_step; + int m_samplestart_step; + int m_samplepos_step; + int m_step_mintime; + int m_step_time; + bool m_step; +}; class floppy_connector: public device_t, public device_slot_interface @@ -259,6 +310,7 @@ public: void set_formats(const floppy_format_type *formats); floppy_image_device *get_device(); + void enable_sound(bool doit) { m_enable_sound = doit; } protected: virtual void device_start(); @@ -266,6 +318,7 @@ protected: private: const floppy_format_type *formats; + bool m_enable_sound; }; diff --git a/src/emu/sound/samples.c b/src/emu/sound/samples.c index 5a47e5d27da..863e30f0832 100644 --- a/src/emu/sound/samples.c +++ b/src/emu/sound/samples.c @@ -595,13 +595,15 @@ bool samples_device::read_flac_sample(emu_file &file, sample_t &sample) //------------------------------------------------- // load_samples - load all the samples in our // attached interface +// Returns true when all samples were successfully read, else false //------------------------------------------------- -void samples_device::load_samples() +bool samples_device::load_samples() { + bool ok = true; // if the user doesn't want to use samples, bail if (!machine().options().samples()) - return; + return false; // iterate over ourself const char *basename = machine().basename(); @@ -631,6 +633,10 @@ void samples_device::load_samples() if (filerr == FILERR_NONE) read_sample(file, m_sample[index]); else if (filerr == FILERR_NOT_FOUND) - osd_printf_warning("Sample '%s' NOT FOUND\n", samplename); + { + logerror("%s: Sample '%s' NOT FOUND\n", tag(), samplename); + ok = false; + } } + return ok; } diff --git a/src/emu/sound/samples.h b/src/emu/sound/samples.h index 45770e127ed..24bb4541766 100644 --- a/src/emu/sound/samples.h +++ b/src/emu/sound/samples.h @@ -92,7 +92,6 @@ protected: // device_sound_interface overrides virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); -private: // internal classes struct channel_t { @@ -111,7 +110,7 @@ private: // internal helpers static bool read_wav_sample(emu_file &file, sample_t &sample); static bool read_flac_sample(emu_file &file, sample_t &sample); - void load_samples(); + bool load_samples(); // internal state std::vector m_channel;