move positions to osd interface
  add special-casing for LFE
  add reverb (currently too subtle, need to find out why)

vgm_visualizer: stop going OOB on the bitmap
This commit is contained in:
Olivier Galibert 2025-06-17 00:55:55 +02:00
parent 292b999b03
commit f0e6df8048
41 changed files with 3271 additions and 275 deletions

View File

@ -99,6 +99,8 @@ files {
MAME_DIR .. "src/frontend/mame/ui/audio_effect_eq.h", MAME_DIR .. "src/frontend/mame/ui/audio_effect_eq.h",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_filter.cpp", MAME_DIR .. "src/frontend/mame/ui/audio_effect_filter.cpp",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_filter.h", MAME_DIR .. "src/frontend/mame/ui/audio_effect_filter.h",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_reverb.cpp",
MAME_DIR .. "src/frontend/mame/ui/audio_effect_reverb.h",
MAME_DIR .. "src/frontend/mame/ui/auditmenu.cpp", MAME_DIR .. "src/frontend/mame/ui/auditmenu.cpp",
MAME_DIR .. "src/frontend/mame/ui/auditmenu.h", MAME_DIR .. "src/frontend/mame/ui/auditmenu.h",
MAME_DIR .. "src/frontend/mame/ui/barcode.cpp", MAME_DIR .. "src/frontend/mame/ui/barcode.cpp",

View File

@ -52,6 +52,7 @@ function osdmodulesbuild()
files { files {
MAME_DIR .. "src/osd/watchdog.cpp", MAME_DIR .. "src/osd/watchdog.cpp",
MAME_DIR .. "src/osd/watchdog.h", MAME_DIR .. "src/osd/watchdog.h",
MAME_DIR .. "src/osd/interface/audio.cpp",
MAME_DIR .. "src/osd/interface/audio.h", MAME_DIR .. "src/osd/interface/audio.h",
MAME_DIR .. "src/osd/interface/inputcode.h", MAME_DIR .. "src/osd/interface/inputcode.h",
MAME_DIR .. "src/osd/interface/inputdev.h", MAME_DIR .. "src/osd/interface/inputdev.h",

View File

@ -739,7 +739,7 @@ void vgmviz_device::draw_waveform(bitmap_rgb32 &bitmap)
bitmap.pix(CHANNEL_HEIGHT + 1 + CHANNEL_CENTER, x) = MED_GRAY; bitmap.pix(CHANNEL_HEIGHT + 1 + CHANNEL_CENTER, x) = MED_GRAY;
const float raw_l = m_audio_buf[1 - m_audio_fill_index][0][((int)m_history_length + 1 + x) % FFT_LENGTH]; const float raw_l = m_audio_buf[1 - m_audio_fill_index][0][((int)m_history_length + 1 + x) % FFT_LENGTH];
const int sample_l = (int)((raw_l - 0.5f) * (CHANNEL_HEIGHT - 1)); const int sample_l = std::clamp((int)((raw_l - 0.5f) * (CHANNEL_HEIGHT - 1)), -CHANNEL_CENTER, CHANNEL_CENTER);
const int dy_l = (sample_l == 0) ? 0 : ((sample_l < 0) ? -1 : 1); const int dy_l = (sample_l == 0) ? 0 : ((sample_l < 0) ? -1 : 1);
const int endy_l = CHANNEL_CENTER; const int endy_l = CHANNEL_CENTER;
int y = endy_l - sample_l; int y = endy_l - sample_l;
@ -750,7 +750,7 @@ void vgmviz_device::draw_waveform(bitmap_rgb32 &bitmap)
} while(y != endy_l); } while(y != endy_l);
const float raw_r = m_audio_buf[1 - m_audio_fill_index][1][((int)m_history_length + 1 + x) % FFT_LENGTH]; const float raw_r = m_audio_buf[1 - m_audio_fill_index][1][((int)m_history_length + 1 + x) % FFT_LENGTH];
const int sample_r = (int)((raw_r - 0.5f) * (CHANNEL_HEIGHT - 1)); const int sample_r = std::clamp((int)((raw_r - 0.5f) * (CHANNEL_HEIGHT - 1)), -CHANNEL_CENTER, CHANNEL_CENTER);
const int dy_r = (sample_r == 0) ? 0 : ((sample_r < 0) ? -1 : 1); const int dy_r = (sample_r == 0) ? 0 : ((sample_r < 0) ? -1 : 1);
const int endy_r = CHANNEL_HEIGHT + 1 + CHANNEL_CENTER; const int endy_r = CHANNEL_HEIGHT + 1 + CHANNEL_CENTER;
y = endy_r - sample_r; y = endy_r - sample_r;

View File

@ -15,13 +15,13 @@ const char *const audio_effect::effect_names[COUNT] = {
"Equalizer" "Equalizer"
}; };
audio_effect *audio_effect::create(int type, u32 sample_rate, audio_effect *def) audio_effect *audio_effect::create(int type, speaker_device *speaker, u32 sample_rate, audio_effect *def)
{ {
switch(type) { switch(type) {
case FILTER: return new audio_effect_filter (sample_rate, def); case FILTER: return new audio_effect_filter (speaker, sample_rate, def);
case COMPRESSOR: return new audio_effect_compressor(sample_rate, def); case COMPRESSOR: return new audio_effect_compressor(speaker, sample_rate, def);
case REVERB: return new audio_effect_reverb (sample_rate, def); case REVERB: return new audio_effect_reverb (speaker, sample_rate, def);
case EQ: return new audio_effect_eq (sample_rate, def); case EQ: return new audio_effect_eq (speaker, sample_rate, def);
} }
return nullptr; return nullptr;
} }
@ -31,8 +31,7 @@ void audio_effect::copy(const emu::detail::output_buffer_flat<sample_t> &src, em
{ {
u32 samples = src.available_samples(); u32 samples = src.available_samples();
dest.prepare_space(samples); dest.prepare_space(samples);
u32 channels = src.channels(); for(u32 channel = 0; channel != m_channels; channel++) {
for(u32 channel = 0; channel != channels; channel++) {
const sample_t *srcd = src.ptrs(channel, 0); const sample_t *srcd = src.ptrs(channel, 0);
sample_t *destd = dest.ptrw(channel, 0); sample_t *destd = dest.ptrw(channel, 0);
std::copy(srcd, srcd + samples, destd); std::copy(srcd, srcd + samples, destd);

View File

@ -6,6 +6,8 @@
#ifndef MAME_EMU_AUDIO_EFFECTS_AEFFECT_H #ifndef MAME_EMU_AUDIO_EFFECTS_AEFFECT_H
#define MAME_EMU_AUDIO_EFFECTS_AEFFECT_H #define MAME_EMU_AUDIO_EFFECTS_AEFFECT_H
#include "speaker.h"
class audio_effect class audio_effect
{ {
public: public:
@ -21,9 +23,9 @@ public:
static const char *const effect_names[COUNT]; static const char *const effect_names[COUNT];
static audio_effect *create(int type, u32 sample_rate, audio_effect *def = nullptr); static audio_effect *create(int type, speaker_device *speaker, u32 sample_rate, audio_effect *def = nullptr);
audio_effect(u32 sample_rate, audio_effect *def) : m_default(def), m_sample_rate(sample_rate) {} audio_effect(speaker_device *speaker, u32 sample_rate, audio_effect *def) : m_default(def), m_speaker(speaker), m_channels(speaker ? speaker->channels() : 0), m_sample_rate(sample_rate) {}
virtual ~audio_effect() = default; virtual ~audio_effect() = default;
void copy(const emu::detail::output_buffer_flat<sample_t> &src, emu::detail::output_buffer_flat<sample_t> &dest) const; void copy(const emu::detail::output_buffer_flat<sample_t> &src, emu::detail::output_buffer_flat<sample_t> &dest) const;
@ -37,7 +39,8 @@ public:
protected: protected:
audio_effect *m_default; audio_effect *m_default;
u32 m_sample_rate; speaker_device *m_speaker;
u32 m_channels, m_sample_rate;
}; };
#endif #endif

View File

@ -7,8 +7,15 @@
#include "compressor.h" #include "compressor.h"
#include "xmlfile.h" #include "xmlfile.h"
audio_effect_compressor::audio_effect_compressor(u32 sample_rate, audio_effect *def) : audio_effect(sample_rate, def) audio_effect_compressor::audio_effect_compressor(speaker_device *speaker, u32 sample_rate, audio_effect *def) :
audio_effect(speaker, sample_rate, def)
{ {
m_slewed_signal.resize(m_channels, -200);
m_gain_reduction.resize(m_channels, 0);
m_input_samples.resize(m_channels, 0);
m_output_samples.resize(m_channels, 0);
m_inertia_velocity.resize(m_channels, 0);
reset_mode(); reset_mode();
reset_attack(); reset_attack();
reset_release(); reset_release();
@ -362,23 +369,14 @@ void audio_effect_compressor::apply(const emu::detail::output_buffer_flat<sample
} }
u32 samples = src.available_samples(); u32 samples = src.available_samples();
u32 channels = src.channels();
dest.prepare_space(samples); dest.prepare_space(samples);
if(m_slewed_signal.empty()) {
m_slewed_signal.resize(channels, -200);
m_gain_reduction.resize(channels, 0);
m_input_samples.resize(channels, 0);
m_output_samples.resize(channels, 0);
m_inertia_velocity.resize(channels, 0);
}
double attack_coefficient = exp(-1/(m_sample_rate * m_attack / 1000)); double attack_coefficient = exp(-1/(m_sample_rate * m_attack / 1000));
double release_coefficient = exp(-1/(m_sample_rate * m_release / 1000)); double release_coefficient = exp(-1/(m_sample_rate * m_release / 1000));
double m_inertia_decay_coefficient = 0.99 + m_inertia_decay * 0.01; double m_inertia_decay_coefficient = 0.99 + m_inertia_decay * 0.01;
for(u32 sample = 0; sample != samples; sample ++) { for(u32 sample = 0; sample != samples; sample ++) {
for(u32 channel = 0; channel != channels; channel ++) { for(u32 channel = 0; channel != m_channels; channel ++) {
double input_db = value_to_db(std::abs(*src.ptrs(channel, sample))) + m_input_gain + std::abs(m_output_samples[channel]) * m_feedback; double input_db = value_to_db(std::abs(*src.ptrs(channel, sample))) + m_input_gain + std::abs(m_output_samples[channel]) * m_feedback;
m_output_samples[channel] = 0; m_output_samples[channel] = 0;
@ -432,11 +430,11 @@ void audio_effect_compressor::apply(const emu::detail::output_buffer_flat<sample
} }
double max_gain = m_gain_reduction[0]; double max_gain = m_gain_reduction[0];
for(u32 channel = 1; channel < channels; channel++) for(u32 channel = 1; channel != m_channels; channel++)
if(m_gain_reduction[channel] > max_gain) if(m_gain_reduction[channel] > max_gain)
max_gain = m_gain_reduction[channel]; max_gain = m_gain_reduction[channel];
for(u32 channel = 0; channel != channels; channel ++) { for(u32 channel = 0; channel != m_channels; channel ++) {
m_gain_reduction[channel] = max_gain * m_channel_link + m_gain_reduction[channel] * (1 - m_channel_link); m_gain_reduction[channel] = max_gain * m_channel_link + m_gain_reduction[channel] * (1 - m_channel_link);
double output_sample = db_to_value(m_input_samples[channel] - m_gain_reduction[channel]); double output_sample = db_to_value(m_input_samples[channel] - m_gain_reduction[channel]);
if(*src.ptrs(channel, sample) < 0) if(*src.ptrs(channel, sample) < 0)

View File

@ -11,7 +11,7 @@
class audio_effect_compressor : public audio_effect class audio_effect_compressor : public audio_effect
{ {
public: public:
audio_effect_compressor(u32 sample_rate, audio_effect *def); audio_effect_compressor(speaker_device *speaker, u32 sample_rate, audio_effect *def);
virtual ~audio_effect_compressor() = default; virtual ~audio_effect_compressor() = default;
virtual int type() const override { return COMPRESSOR; } virtual int type() const override { return COMPRESSOR; }

View File

@ -12,8 +12,11 @@
// [Zölzer 2011] "DAFX: Digital Audio Effects", Udo Zölzer, Second Edition, Wiley publishing, 2011 (Tables 2.3 and 2.4) // [Zölzer 2011] "DAFX: Digital Audio Effects", Udo Zölzer, Second Edition, Wiley publishing, 2011 (Tables 2.3 and 2.4)
// [Zölzer 2008] "Digital Audio Signal Processing", Udo Zölzer, Second Edition, Wiley publishing, 2008 (Tables 5.3, 5.4 and 5.5) // [Zölzer 2008] "Digital Audio Signal Processing", Udo Zölzer, Second Edition, Wiley publishing, 2008 (Tables 5.3, 5.4 and 5.5)
audio_effect_eq::audio_effect_eq(u32 sample_rate, audio_effect *def) : audio_effect(sample_rate, def) audio_effect_eq::audio_effect_eq(speaker_device *speaker, u32 sample_rate, audio_effect *def) :
audio_effect(speaker, sample_rate, def)
{ {
m_history.resize(m_channels);
// Minimal init to avoid using uninitialized values when reset_* // Minimal init to avoid using uninitialized values when reset_*
// recomputes filters // recomputes filters
@ -322,11 +325,8 @@ void audio_effect_eq::apply(const emu::detail::output_buffer_flat<sample_t> &src
u32 samples = src.available_samples(); u32 samples = src.available_samples();
dest.prepare_space(samples); dest.prepare_space(samples);
u32 channels = src.channels();
if(m_history.empty())
m_history.resize(channels);
for(u32 channel = 0; channel != channels; channel++) { for(u32 channel = 0; channel != m_channels; channel++) {
const sample_t *srcd = src.ptrs(channel, 0); const sample_t *srcd = src.ptrs(channel, 0);
sample_t *destd = dest.ptrw(channel, 0); sample_t *destd = dest.ptrw(channel, 0);
for(u32 sample = 0; sample != samples; sample++) { for(u32 sample = 0; sample != samples; sample++) {

View File

@ -13,7 +13,7 @@ class audio_effect_eq : public audio_effect
public: public:
enum { BANDS = 5 }; enum { BANDS = 5 };
audio_effect_eq(u32 sample_rate, audio_effect *def); audio_effect_eq(speaker_device *speaker, u32 sample_rate, audio_effect *def);
virtual ~audio_effect_eq() = default; virtual ~audio_effect_eq() = default;
virtual int type() const override { return EQ; } virtual int type() const override { return EQ; }

View File

@ -13,8 +13,11 @@
// [Zölzer 2011] "DAFX: Digital Audio Effects", Udo Zölzer, Second Edition, Wiley publishing, 2011 (Table 2.2) // [Zölzer 2011] "DAFX: Digital Audio Effects", Udo Zölzer, Second Edition, Wiley publishing, 2011 (Table 2.2)
audio_effect_filter::audio_effect_filter(u32 sample_rate, audio_effect *def) : audio_effect(sample_rate, def) audio_effect_filter::audio_effect_filter(speaker_device *speaker, u32 sample_rate, audio_effect *def) :
audio_effect(speaker, sample_rate, def)
{ {
m_history.resize(m_channels);
// Minimal init to avoid using uninitialized values when reset_* // Minimal init to avoid using uninitialized values when reset_*
// recomputes filters // recomputes filters
m_fl = m_fh = 1000; m_fl = m_fh = 1000;
@ -159,11 +162,8 @@ void audio_effect_filter::apply(const emu::detail::output_buffer_flat<sample_t>
u32 samples = src.available_samples(); u32 samples = src.available_samples();
dest.prepare_space(samples); dest.prepare_space(samples);
u32 channels = src.channels();
if(m_history.empty())
m_history.resize(channels);
for(u32 channel = 0; channel != channels; channel++) { for(u32 channel = 0; channel != m_channels; channel++) {
const sample_t *srcd = src.ptrs(channel, 0); const sample_t *srcd = src.ptrs(channel, 0);
sample_t *destd = dest.ptrw(channel, 0); sample_t *destd = dest.ptrw(channel, 0);
for(u32 sample = 0; sample != samples; sample++) { for(u32 sample = 0; sample != samples; sample++) {

View File

@ -11,7 +11,7 @@
class audio_effect_filter : public audio_effect class audio_effect_filter : public audio_effect
{ {
public: public:
audio_effect_filter(u32 sample_rate, audio_effect *def); audio_effect_filter(speaker_device *speaker, u32 sample_rate, audio_effect *def);
virtual ~audio_effect_filter() = default; virtual ~audio_effect_filter() = default;
virtual int type() const override { return FILTER; } virtual int type() const override { return FILTER; }

File diff suppressed because it is too large Load Diff

View File

@ -8,10 +8,12 @@
#include "aeffect.h" #include "aeffect.h"
#include <random>
class audio_effect_reverb : public audio_effect class audio_effect_reverb : public audio_effect
{ {
public: public:
audio_effect_reverb(u32 sample_rate, audio_effect *def); audio_effect_reverb(speaker_device *speaker, u32 sample_rate, audio_effect *def);
virtual ~audio_effect_reverb() = default; virtual ~audio_effect_reverb() = default;
virtual int type() const override { return REVERB; } virtual int type() const override { return REVERB; }
@ -19,6 +21,420 @@ public:
virtual void config_load(util::xml::data_node const *ef_node) override; virtual void config_load(util::xml::data_node const *ef_node) override;
virtual void config_save(util::xml::data_node *ef_node) const override; virtual void config_save(util::xml::data_node *ef_node) const override;
virtual void default_changed() override; virtual void default_changed() override;
void set_mode(u32 mode);
void set_early_tap_setup(u32 index);
void set_early_damping(double cutoff);
void set_stereo_width(double width);
void set_early_room_size(double size);
void set_late_room_size(double size);
void set_late_spin(double speed);
void set_late_wander(double wander);
void set_late_diffusion(double value);
void set_late_damping(double cutoff);
void set_late_predelay(double delay);
void set_late_global_decay(float value);
void set_dry_level(double level);
void set_early_level(double level);
void set_late_level(double level);
void set_early_to_late_level(double level);
u32 mode() const { return m_mode; }
u32 early_tap_setup() const { return m_early_tap_setup; }
double early_damping() const { return m_early_damping; }
double stereo_width() const { return m_stereo_width; }
double early_room_size() const { return m_early_room_size; }
double late_room_size() const { return m_late_room_size; }
double late_spin() const { return m_late_spin; }
double late_wander() const { return m_late_wander; }
double late_diffusion() const { return m_late_diffusion; }
double late_damping() const { return m_late_damping; }
double late_predelay() const { return m_late_predelay; }
float late_global_decay() const { return m_late_global_decay; }
double dry_level() const { return m_dry_level; }
double early_level() const { return m_early_level; }
double late_level() const { return m_late_level; }
double early_to_late_level() const { return m_early_to_late_level; }
bool isset_mode() const { return m_isset_mode; }
bool isset_early_tap_setup() const { return m_isset_early_tap_setup; }
bool isset_early_damping() const { return m_isset_early_damping; }
bool isset_stereo_width() const { return m_isset_stereo_width; }
bool isset_early_room_size() const { return m_isset_early_room_size; }
bool isset_late_room_size() const { return m_isset_late_room_size; }
bool isset_late_spin() const { return m_isset_late_spin; }
bool isset_late_wander() const { return m_isset_late_wander; }
bool isset_late_diffusion() const { return m_isset_late_diffusion; }
bool isset_late_damping() const { return m_isset_late_damping; }
bool isset_late_predelay() const { return m_isset_late_predelay; }
bool isset_late_global_decay() const { return m_isset_late_global_decay; }
bool isset_dry_level() const { return m_isset_dry_level; }
bool isset_early_level() const { return m_isset_early_level; }
bool isset_late_level() const { return m_isset_late_level; }
bool isset_early_to_late_level() const { return m_isset_early_to_late_level; }
void reset_mode();
void reset_early_tap_setup();
void reset_early_damping();
void reset_stereo_width();
void reset_early_room_size();
void reset_late_room_size();
void reset_late_spin();
void reset_late_wander();
void reset_late_diffusion();
void reset_late_damping();
void reset_late_predelay();
void reset_late_global_decay();
void reset_dry_level();
void reset_early_level();
void reset_late_level();
void reset_early_to_late_level();
static u32 preset_count();
static const char *preset_name(u32 id);
static u32 early_tap_setup_count();
static const char *early_tap_setup_name(u32 id);
void load_preset(u32 id);
private:
struct preset {
const char *name;
u32 early_tap_setup;
double early_damping;
double stereo_width;
double early_room_size;
double late_room_size;
double late_spin;
double late_wander;
double late_diffusion;
double late_damping;
double late_predelay;
float late_global_decay;
double dry_level;
double early_level;
double late_level;
double early_to_late_level;
};
static const preset presets[];
enum { INPUT_DIFFUSION_ALLPASS = 10, CROSS_DIFFUSION_ALLPASS = 4 };
struct early_reverb_tap_map {
const char *name;
u32 m_count[2];
float m_delay[2][18];
float m_gain[2][18];
};
static const early_reverb_tap_map tap_maps[15];
struct delay_buffer {
enum { D_MASK = 8191 };
sample_t m_samples[D_MASK+1];
u32 m_index;
void clear();
void push(sample_t value);
sample_t get(u32 dist) const;
sample_t geti(float dist) const; // Get with interpolation
delay_buffer() { clear(); }
};
struct delay {
delay_buffer m_delay_buffer;
std::vector<u32> m_taps;
void clear();
void set_tap(u32 tap, u32 dist);
void push(sample_t value);
sample_t get(u32 tap) const;
sample_t process(sample_t value) { push(value); return get(0); }
delay() { clear(); }
};
struct iir1h {
sample_t m_y1;
void clear();
iir1h() { clear(); }
};
struct iir1 {
float m_a2, m_b1, m_b2;
sample_t process(iir1h &h, sample_t x0);
void prepare_lpf(double cutoff, u32 sample_rate);
void prepare_hpf(double cutoff, u32 sample_rate);
};
struct iir2h {
sample_t m_x1, m_x2, m_y1, m_y2;
void clear();
iir2h() { clear(); }
};
struct iir2 {
float m_a1, m_a2, m_b0, m_b1, m_b2;
sample_t process(iir2h &h, sample_t x0);
void prepare_lpf(double cutoff, double bw, u32 sample_rate);
void prepare_apf(double cutoff, double bw, u32 sample_rate);
};
struct dccuth {
float m_y1, m_y2;
void clear();
dccuth() { clear(); }
};
struct dccut {
float m_gain;
sample_t process(dccuth &h, sample_t x0);
void prepare(double cutoff, u32 sample_rate);
};
struct pink {
enum { SIZE = 1 << 15 };
std::mt19937 m_rng;
std::uniform_real_distribution<sample_t> m_dis;
sample_t m_buffer[SIZE];
u32 m_index;
void clear();
pink() : m_rng(std::random_device()()), m_dis(-1, 1) { clear(); }
sample_t process();
};
struct lfo {
float m_c, m_s, m_rc, m_rs;
u32 m_count;
void clear();
lfo() : m_rc(1), m_rs(0) { clear(); }
void prepare(double speed, u32 sample_rate);
float process();
};
struct allpass {
delay_buffer m_delay_buffer;
float m_gain;
u32 m_delay;
void clear();
sample_t process(sample_t input);
void set_gain(float base);
void set_delay(u32 base);
allpass() { clear(); }
};
struct allpass_m {
delay_buffer m_delay_buffer;
float m_base_gain;
float m_base_delay, m_mod_delay;
void clear();
sample_t process(sample_t input, float delay_mod, float gain_mod);
void set_gain(float base);
void set_delay(float base, float mod);
allpass_m() { clear(); }
};
struct allpass_md {
delay_buffer m_delay_buffer;
float m_base_gain, m_decay;
float m_base_delay, m_mod_delay;
void clear();
sample_t process(sample_t input, float delay_mod, float gain_mod);
void set_gain(float base);
void set_delay(float base, float mod);
void set_decay(float base);
allpass_md() { clear(); }
};
struct allpass2 {
delay_buffer m_delay_buffer_1, m_delay_buffer_2;
float m_gain_1, m_gain_2, m_decay_1, m_decay_2;
u32 m_delay_1, m_delay_2;
std::vector<u32> m_taps_1, m_taps_2;
void clear();
sample_t process(sample_t input);
void set_gain_1(float base);
void set_gain_2(float base);
void set_delays(u32 base_1, u32 base_2);
void set_decay_1(float base);
void set_decay_2(float base);
void set_tap_1(u32 tap, u32 dist);
void set_tap_2(u32 tap, u32 dist);
sample_t get_1(u32 tap) const;
sample_t get_2(u32 tap) const;
allpass2() { clear(); }
};
struct allpass3m {
delay_buffer m_delay_buffer_1, m_delay_buffer_2, m_delay_buffer_3;
float m_gain_1, m_gain_2, m_gain_3, m_decay_1, m_decay_2, m_decay_3;
u32 m_base_delay_1, m_mod_delay_1, m_delay_2, m_delay_3;
std::vector<u32> m_taps_1, m_taps_2, m_taps_3;
void clear();
sample_t process(sample_t input, float delay_mod);
void set_gain_1(float base);
void set_gain_2(float base);
void set_gain_3(float base);
void set_delays(u32 base_1, u32 mod_1, u32 base_2, u32 base_3);
void set_decay_1(float base);
void set_decay_2(float base);
void set_decay_3(float base);
void set_tap_1(u32 tap, u32 dist);
void set_tap_2(u32 tap, u32 dist);
void set_tap_3(u32 tap, u32 dist);
sample_t get_1(u32 tap) const;
sample_t get_2(u32 tap) const;
sample_t get_3(u32 tap) const;
allpass3m() { clear(); }
};
struct comb {
delay_buffer m_delay_buffer;
sample_t m_filter_history;
u32 m_size;
void clear();
sample_t process(sample_t input, float feedback);
void set_size(u32 size);
comb() { clear(); }
};
enum ch_type_t { T_MONO, T_LEFT, T_RIGHT };
u32 m_mode;
u32 m_early_tap_setup;
double m_early_damping;
double m_stereo_width;
double m_early_room_size;
double m_late_room_size;
double m_late_spin;
double m_late_wander;
double m_late_diffusion;
double m_late_damping;
double m_late_predelay;
float m_late_global_decay;
double m_dry_level;
double m_early_level;
double m_late_level;
double m_early_to_late_level;
bool m_isset_mode;
bool m_isset_early_tap_setup;
bool m_isset_early_damping;
bool m_isset_stereo_width;
bool m_isset_early_room_size;
bool m_isset_late_room_size;
bool m_isset_late_spin;
bool m_isset_late_wander;
bool m_isset_late_diffusion;
bool m_isset_late_damping;
bool m_isset_late_predelay;
bool m_isset_late_global_decay;
bool m_isset_dry_level;
bool m_isset_early_level;
bool m_isset_late_level;
bool m_isset_early_to_late_level;
std::vector<ch_type_t> m_ch_type;
std::vector<int> m_ch_pair;
iir1 m_early_lpf, m_early_hpf;
iir2 m_early_diffusion_allpass, m_early_cross_allpass;
dccut m_late_dccut;
pink m_late_noise;
lfo m_late_lfo1, m_late_lfo2;
iir1 m_late_lfo1_lpf, m_late_lfo2_lpf, m_late_input_damping, m_late_damping_1;
iir2 m_late_bass, m_late_damping_2, m_late_output_lpf;
std::vector<iir1h> m_early_lpf_h, m_early_hpf_h;
std::vector<iir2h> m_early_diffusion_allpass_h, m_early_cross_allpass_h;
std::vector<dccuth> m_late_dccut_h;
iir1h m_late_lfo1_lpf_h, m_late_lfo2_lpf_h;
std::vector<delay_buffer> m_early_delays;
std::vector<delay_buffer> m_early_xdelays;
std::vector<std::vector<allpass_m>> m_late_input_diffusion;
std::vector<std::vector<allpass>> m_late_cross_diffusion;
std::vector<iir1h> m_late_input_damping_h, m_late_damping_1_h;
std::vector<iir2h> m_late_bass_h, m_late_damping_2_h, m_late_output_lpf_h;
std::vector<allpass_md> m_late_step_1, m_late_step_3;
std::vector<allpass2> m_late_step_5;
std::vector<allpass3m> m_late_step_7;
std::vector<delay> m_late_step_2, m_late_step_4, m_late_step_6, m_late_step_8;
std::vector<comb> m_late_comb;
std::vector<delay> m_late_final_delay;
std::vector<sample_t> m_early_in, m_early_wet, m_early_out;
std::vector<sample_t> m_late_in, m_late_diff, m_late_cross, m_late_cross2, m_late_pre_out, m_late_out;
float m_wet1, m_wet2;
float m_early_room_size_ratio;
float m_late_room_size_ratio;
float m_late_wander_actual;
float m_late_modulation_noise_1, m_late_modulation_noise_2;
float m_late_crossfeed;
float m_late_decay_0, m_late_decay_1, m_late_decay_2, m_late_decay_3, m_late_decay_f;
float m_late_loop_decay, m_late_bass_boost;
float m_actual_dry_level, m_actual_early_level, m_actual_late_level, m_actual_early_to_late_level;
u32 m_early_tap_dists[2][18];
u32 m_early_xdelays_dist;
const preset *m_default_preset;
void commit_early_tap_setup();
void commit_early_damping();
void commit_stereo_width();
void commit_early_room_size();
void commit_late_room_size();
void commit_late_decay();
void commit_late_spin();
void commit_late_wander();
void commit_late_diffusion();
void commit_late_damping();
void commit_late_predelay();
void commit_dry_level();
void commit_early_level();
void commit_late_level();
void commit_early_to_late_level();
void set_early_hpf(double cutoff);
void set_early_diffusion_ap(double cutoff, double bw);
void set_early_cross_ap(double cutoff, double bw);
void set_early_multichannel_delay(double delay);
void set_late_dccut(double cutoff);
void set_late_spin_limit_1(double cutoff);
void set_late_spin_limit_2(double cutoff);
void set_late_modulation_noise_1(double mod);
void set_late_modulation_noise_2(double mod);
void set_late_diffusion_1(double value);
void set_late_diffusion_2(double value);
void set_late_diffusion_3(double value);
void set_late_diffusion_4(double value);
void set_late_input_damping(double cutoff);
void set_late_damping_2(double cutoff, double bw);
void set_late_decay_0(float value);
void set_late_decay_1(float value);
void set_late_decay_2(float value);
void set_late_decay_3(float value);
void set_late_decay_f(float value);
void set_late_bass_allpass(double cutoff, double bw);
void set_late_spin_to_wander(double value);
static const preset *find_preset(std::string name);
static bool is_prime(u32 value);
static u32 find_prime(u32 v);
}; };
#endif #endif

View File

@ -308,7 +308,8 @@ sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 sample
m_sync_timer(nullptr), m_sync_timer(nullptr),
m_callback(std::move(callback)) m_callback(std::move(callback))
{ {
sound_assert(outputs > 0 || inputs > 0); if(inputs == 0 && outputs == 0)
fatalerror("Device %s requiring to create a stream without inputs or outputs\n", device.tag());
// create a name // create a name
m_name = m_device.name(); m_name = m_device.name();
@ -854,7 +855,7 @@ void sound_manager::after_devices_init()
// Create the default effect chain // Create the default effect chain
for(u32 effect = 0; effect != audio_effect::COUNT; effect++) for(u32 effect = 0; effect != audio_effect::COUNT; effect++)
m_default_effects.emplace_back(audio_effect::create(effect, machine().sample_rate(), nullptr)); m_default_effects.emplace_back(audio_effect::create(effect, nullptr, machine().sample_rate(), nullptr));
// Inventory speakers and microphones // Inventory speakers and microphones
m_outputs_count = 0; m_outputs_count = 0;
@ -862,7 +863,7 @@ void sound_manager::after_devices_init()
dev.set_id(m_speakers.size()); dev.set_id(m_speakers.size());
m_speakers.emplace_back(speaker_info(dev, machine().sample_rate(), m_outputs_count)); m_speakers.emplace_back(speaker_info(dev, machine().sample_rate(), m_outputs_count));
for(u32 effect = 0; effect != audio_effect::COUNT; effect++) for(u32 effect = 0; effect != audio_effect::COUNT; effect++)
m_speakers.back().m_effects[effect].m_effect.reset(audio_effect::create(effect, machine().sample_rate(), m_default_effects[effect].get())); m_speakers.back().m_effects[effect].m_effect.reset(audio_effect::create(effect, &dev, machine().sample_rate(), m_default_effects[effect].get()));
m_outputs_count += dev.inputs(); m_outputs_count += dev.inputs();
} }
@ -1980,17 +1981,24 @@ void sound_manager::generate_mapping()
// Find where to map a sound_io channel into a node's channels depending on their positions // Find where to map a sound_io channel into a node's channels depending on their positions
std::vector<u32> sound_manager::find_channel_mapping(const std::array<double, 3> &position, const osd::audio_info::node_info *node) std::vector<u32> sound_manager::find_channel_mapping(const osd::channel_position &pos, const osd::audio_info::node_info *node)
{ {
std::vector<u32> result; std::vector<u32> result;
if(position[0] == 0 && position[1] == 0 && position[2] == 0) if(pos.is_lfe()) {
for(u32 port = 0; port != node->m_port_positions.size(); port++)
if(node->m_port_positions[port].is_lfe())
result.push_back(port);
return result; return result;
}
if(pos.is_onreq())
return result;
double best_dist = -1; double best_dist = -1;
for(u32 port = 0; port != node->m_port_positions.size(); port++) for(u32 port = 0; port != node->m_port_positions.size(); port++)
if(sound_io_device::mapping_allowed(node->m_port_positions[port])) { if(!node->m_port_positions[port].is_onreq() && !node->m_port_positions[port].is_lfe()) {
double dx = position[0] - node->m_port_positions[port][0]; double dx = pos.m_x - node->m_port_positions[port].m_z;
double dy = position[1] - node->m_port_positions[port][1]; double dy = pos.m_y - node->m_port_positions[port].m_y;
double dz = position[2] - node->m_port_positions[port][2]; double dz = pos.m_z - node->m_port_positions[port].m_z;
double dist = dx*dx + dy*dy + dz*dz; double dist = dx*dx + dy*dy + dz*dz;
if(best_dist == -1 || dist < best_dist) { if(best_dist == -1 || dist < best_dist) {
best_dist = dist; best_dist = dist;
@ -2496,12 +2504,10 @@ void sound_manager::mapping_update()
if(port_count < node.m_sources) if(port_count < node.m_sources)
port_count = node.m_sources; port_count = node.m_sources;
for(uint32_t port = 0; port != port_count; port++) for(uint32_t port = 0; port != port_count; port++)
LOG_OUTPUT_FUNC(" %s %s [%g %g %g]\n", LOG_OUTPUT_FUNC(" %s %s [%s]\n",
(port < node.m_sinks) ? ((port < node.m_sources) ? "<>" : ">") : "<", port < node.m_sinks ? port < node.m_sources ? "<>" : ">" : "<",
node.m_port_names[port], node.m_port_names[port].c_str(),
node.m_port_positions[port][0], node.m_port_positions[port].name());
node.m_port_positions[port][1],
node.m_port_positions[port][2]);
} }
LOG_OUTPUT_FUNC("- streams:\n"); LOG_OUTPUT_FUNC("- streams:\n");
for(const auto &stream : m_osd_info.m_streams) { for(const auto &stream : m_osd_info.m_streams) {

View File

@ -50,8 +50,8 @@
By default, the inputs will have been resampled to match the output By default, the inputs will have been resampled to match the output
sample rate, unless otherwise specified. sample rate, unless otherwise specified.
SOUND_DISABLE_THREADING if to be defined when your environment does SOUND_DISABLE_THREADING is to be defined when your environment does
not support threads (e.g. emscripten). The effects suddendly become not support threads (e.g. emscripten). The effects suddenly become
costly then though. costly then though.
***************************************************************************/ ***************************************************************************/
@ -84,23 +84,6 @@ constexpr u32 SAMPLE_RATE_INPUT_ADAPTIVE = 0xffffffff;
constexpr u32 SAMPLE_RATE_OUTPUT_ADAPTIVE = 0xfffffffe; constexpr u32 SAMPLE_RATE_OUTPUT_ADAPTIVE = 0xfffffffe;
constexpr u32 SAMPLE_RATE_ADAPTIVE = 0xfffffffd; constexpr u32 SAMPLE_RATE_ADAPTIVE = 0xfffffffd;
//**************************************************************************
// DEBUGGING
//**************************************************************************
// turn this on to enable aggressive assertions and other checks
#ifdef MAME_DEBUG
#define SOUND_DEBUG (1)
#else
#define SOUND_DEBUG (1)
#endif
// if SOUND_DEBUG is on, make assertions fire regardless of MAME_DEBUG
#if (SOUND_DEBUG)
#define sound_assert(x) do { if (!(x)) { osd_printf_error("sound_assert: " #x "\n"); osd_break_into_debugger("sound_assert: " #x "\n"); } } while (0)
#else
#define sound_assert assert
#endif
using stream_update_delegate = delegate<void (sound_stream &stream)>; using stream_update_delegate = delegate<void (sound_stream &stream)>;
class audio_effect; class audio_effect;
@ -599,7 +582,7 @@ private:
void update(s32); void update(s32);
// handle mixing mapping update if needed // handle mixing mapping update if needed
static std::vector<u32> find_channel_mapping(const std::array<double, 3> &position, const osd::audio_info::node_info *node); static std::vector<u32> find_channel_mapping(const osd::channel_position &pos, const osd::audio_info::node_info *node);
void startup_cleanups(); void startup_cleanups();
void streams_update(); void streams_update();
template<bool is_output, typename S> void apply_osd_changes(std::vector<S> &streams); template<bool is_output, typename S> void apply_osd_changes(std::vector<S> &streams);

View File

@ -18,37 +18,21 @@
DEFINE_DEVICE_TYPE(SPEAKER, speaker_device, "speaker", "Speaker") DEFINE_DEVICE_TYPE(SPEAKER, speaker_device, "speaker", "Speaker")
DEFINE_DEVICE_TYPE(MICROPHONE, microphone_device, "microphone", "Microphone") DEFINE_DEVICE_TYPE(MICROPHONE, microphone_device, "microphone", "Microphone")
const sound_io_device::position_name_mapping sound_io_device::position_name_mappings[] = {
{ 0.0, 0.0, 1.0, "Front center" },
{ -0.2, 0.0, 1.0, "Front left" },
{ 0.0, -0.5, 1.0, "Front floor" },
{ 0.2, 0.0, 1.0, "Front right" },
{ 0.0, 0.0, -0.5, "Rear center" },
{ -0.2, 0.0, -0.5, "Rear left" },
{ 0.2, 0.0, -0.5, "Read right" },
{ 0.0, 0.0, -0.1, "Headrest center" },
{ -0.1, 0.0, -0.1, "Headrest left" },
{ 0.1, 0.0, -0.1, "Headrest right" },
{ 0.0, -0.5, 0.0, "Seat" },
{ 0.0, -0.2, 0.1, "Backrest" },
{ }
};
std::string sound_io_device::get_position_name(u32 channel) const
{
for(unsigned int i = 0; position_name_mappings[i].m_name; i++)
if(m_positions[channel][0] == position_name_mappings[i].m_x && m_positions[channel][1] == position_name_mappings[i].m_y && m_positions[channel][2] == position_name_mappings[i].m_z)
return position_name_mappings[i].m_name;
return util::string_format("#%d", channel);
}
sound_io_device &sound_io_device::set_position(u32 channel, double x, double y, double z) sound_io_device &sound_io_device::set_position(u32 channel, double x, double y, double z)
{ {
if(channel >= m_positions.size()) if(channel >= m_positions.size())
fatalerror("%s: Requested channel %d on %d channel device\n", tag(), channel, m_positions.size()); fatalerror("%s: Requested channel %d on %d channel device\n", tag(), channel, m_positions.size());
m_positions[channel][0] = x; m_positions[channel].m_x = x;
m_positions[channel][1] = y; m_positions[channel].m_y = y;
m_positions[channel][2] = z; m_positions[channel].m_z = z;
return *this;
}
sound_io_device &sound_io_device::set_position(u32 channel, const osd::channel_position &pos)
{
if(channel >= m_positions.size())
fatalerror("%s: Requested channel %d on %d channel device\n", tag(), channel, m_positions.size());
m_positions[channel] = pos;
return *this; return *this;
} }

View File

@ -41,30 +41,32 @@ DECLARE_DEVICE_TYPE(MICROPHONE, microphone_device)
class sound_io_device : public device_t, public device_sound_interface class sound_io_device : public device_t, public device_sound_interface
{ {
public: public:
virtual ~sound_io_device(); virtual ~sound_io_device();
// configuration helpers // configuration helpers
sound_io_device &set_position(u32 channel, double x, double y, double z); sound_io_device &set_position(u32 channel, double x, double y, double z);
sound_io_device &front_center(u32 channel = 0) { return set_position(channel, 0.0, 0.0, 1.0); } sound_io_device &set_position(u32 channel, const osd::channel_position &pos);
sound_io_device &front_left(u32 channel = 0) { return set_position(channel, -0.2, 0.0, 1.0); } sound_io_device &front_center(u32 channel = 0) { return set_position(channel, osd::channel_position::FC); }
sound_io_device &front_floor(u32 channel = 0) { return set_position(channel, 0.0, -0.5, 1.0); } sound_io_device &front_left(u32 channel = 0) { return set_position(channel, osd::channel_position::FL); }
sound_io_device &front_right(u32 channel = 0) { return set_position(channel, 0.2, 0.0, 1.0); } sound_io_device &front_right(u32 channel = 0) { return set_position(channel, osd::channel_position::FR); }
sound_io_device &rear_center(u32 channel = 0) { return set_position(channel, 0.0, 0.0, -0.5); } sound_io_device &rear_center(u32 channel = 0) { return set_position(channel, osd::channel_position::RC); }
sound_io_device &rear_left(u32 channel = 0) { return set_position(channel, -0.2, 0.0, -0.5); } sound_io_device &rear_left(u32 channel = 0) { return set_position(channel, osd::channel_position::RL); }
sound_io_device &rear_right(u32 channel = 0) { return set_position(channel, 0.2, 0.0, -0.5); } sound_io_device &rear_right(u32 channel = 0) { return set_position(channel, osd::channel_position::RR); }
sound_io_device &headrest_center(u32 channel = 0) { return set_position(channel, 0.0, 0.0, -0.1); } sound_io_device &headrest_center(u32 channel = 0) { return set_position(channel, osd::channel_position::HC); }
sound_io_device &headrest_left(u32 channel = 0) { return set_position(channel, -0.1, 0.0, -0.1); } sound_io_device &headrest_left(u32 channel = 0) { return set_position(channel, osd::channel_position::HL); }
sound_io_device &headrest_right(u32 channel = 0) { return set_position(channel, 0.1, 0.0, -0.1); } sound_io_device &headrest_right(u32 channel = 0) { return set_position(channel, osd::channel_position::RC); }
sound_io_device &seat(u32 channel = 0) { return set_position(channel, 0.0, -0.5, 0.0); } sound_io_device &backrest(u32 channel = 0) { return set_position(channel, osd::channel_position::BACKREST); }
sound_io_device &backrest(u32 channel = 0) { return set_position(channel, 0.0, -0.2, 0.1); } sound_io_device &unknown(u32 channel = 0) { return set_position(channel, osd::channel_position::UNKNOWN); }
sound_io_device &unknown(u32 channel = 0) { return set_position(channel, 0.0, 0.0, 0.0); } sound_io_device &map_on_request_only(u32 channel = 0) { return set_position(channel, osd::channel_position::ONREQ); }
sound_io_device &map_on_request_only(u32 channel = 0) { return set_position(channel, 0.0, 0.0, 10.0); } sound_io_device &lfe(u32 channel = 0) { return set_position(channel, osd::channel_position::LFE); }
sound_io_device &front() { return front_left(0).front_right(1); } sound_io_device &front() { return front_left(0).front_right(1); }
sound_io_device &rear() { return rear_left(0).rear_right(1); } sound_io_device &rear() { return rear_left(0).rear_right(1); }
sound_io_device &corners() { return front_left(0).front_right(1).rear_left(2).rear_right(3); } sound_io_device &corners() { return front_left(0).front_right(1).rear_left(2).rear_right(3); }
int channels() const { return m_positions.size(); } int channels() const { return m_positions.size(); }
std::array<double, 3> get_position(u32 channel) const { return m_positions[channel]; } const osd::channel_position &get_position(u32 channel) const { return m_positions[channel]; }
std::string get_position_name(u32 channel) const;
virtual bool is_output() const = 0; virtual bool is_output() const = 0;
void set_id(int id) { m_id = id; } void set_id(int id) { m_id = id; }
@ -72,20 +74,9 @@ public:
sound_stream *stream() const { return m_stream; } sound_stream *stream() const { return m_stream; }
static bool mapping_allowed(const std::array<double, 3> &position) {
return position[0] != 0 || position[1] != 0 || position[2] != 10.0;
}
protected: protected:
struct position_name_mapping {
double m_x, m_y, m_z;
const char *m_name;
};
static const position_name_mapping position_name_mappings[];
// configuration state // configuration state
std::vector<std::array<double, 3>> m_positions; std::vector<osd::channel_position> m_positions;
sound_stream *m_stream; sound_stream *m_stream;
int m_id; int m_id;

View File

@ -1696,9 +1696,9 @@ void lua_engine::initialize()
{ {
auto pos = iodev->get_position(channel); auto pos = iodev->get_position(channel);
auto table = sol().create_table(); auto table = sol().create_table();
table[1] = pos[0]; table[1] = pos.m_x;
table[2] = pos[1]; table[2] = pos.m_y;
table[3] = pos[2]; table[3] = pos.m_z;
pos_table[channel+1] = table; pos_table[channel+1] = table;
} }
return pos_table; return pos_table;
@ -1710,7 +1710,7 @@ void lua_engine::initialize()
auto *iodev = dynamic_cast<sound_io_device *>(&dev.device()); auto *iodev = dynamic_cast<sound_io_device *>(&dev.device());
if (iodev) if (iodev)
for(int channel=0; channel != iodev->channels(); channel++) for(int channel=0; channel != iodev->channels(); channel++)
pos_table[channel+1] = iodev->get_position_name(channel); pos_table[channel+1] = iodev->get_position(channel).name();
return pos_table; return pos_table;
}); });

View File

@ -0,0 +1,655 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/*********************************************************************
ui/audio_effect_reverb.cpp
Reverb configuration
*********************************************************************/
#include "emu.h"
#include "ui/audio_effect_reverb.h"
#include "audio_effects/aeffect.h"
#include "audio_effects/reverb.h"
#include "ui/ui.h"
namespace ui {
menu_audio_effect_reverb::menu_audio_effect_reverb(mame_ui_manager &mui, render_container &container, u16 chain, u16 entry, audio_effect *effect)
: menu(mui, container)
{
m_chain = chain;
m_entry = entry;
m_preset = 0;
m_effect = static_cast<audio_effect_reverb *>(effect);
set_heading(util::string_format("%s #%u", chain == 0xffff ? _("Default") : machine().sound().effect_chain_tag(chain), entry+1));
set_process_flags(PROCESS_LR_REPEAT | PROCESS_LR_ALWAYS);
}
menu_audio_effect_reverb::~menu_audio_effect_reverb()
{
}
bool menu_audio_effect_reverb::handle(event const *ev)
{
if(!ev)
return false;
bool alt_pressed = machine().input().code_pressed(KEYCODE_LALT) || machine().input().code_pressed(KEYCODE_RALT);
bool ctrl_pressed = machine().input().code_pressed(KEYCODE_LCONTROL) || machine().input().code_pressed(KEYCODE_RCONTROL);
bool shift_pressed = machine().input().code_pressed(KEYCODE_LSHIFT) || machine().input().code_pressed(KEYCODE_RSHIFT);
switch(ev->iptkey) {
case IPT_UI_SELECT:
if(uintptr_t(ev->itemref) == PRESET) {
m_effect->load_preset(m_preset);
reset(reset_options::REMEMBER_POSITION);
return true;
}
break;
case IPT_UI_LEFT: {
switch(uintptr_t(ev->itemref)) {
case MODE:
m_effect->set_mode(0);
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case PRESET:
if(m_preset != 0)
m_preset --;
reset(reset_options::REMEMBER_POSITION);
return true;
case DRYL:
m_effect->set_dry_level(change_percent(m_effect->dry_level(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case EL:
m_effect->set_early_level(change_percent(m_effect->early_level(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LL:
m_effect->set_late_level(change_percent(m_effect->late_level(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case E2LL:
m_effect->set_early_to_late_level(change_percent(m_effect->early_to_late_level(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case ERS:
m_effect->set_early_room_size(change_percent(m_effect->early_room_size(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LRS:
m_effect->set_late_room_size(change_percent(m_effect->late_room_size(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case SW:
m_effect->set_stereo_width(change_percent(m_effect->stereo_width(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDIFF:
m_effect->set_late_diffusion(change_percent(m_effect->late_diffusion(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LWANDER:
m_effect->set_late_wander(change_percent(m_effect->late_wander(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case EDAMP:
m_effect->set_early_damping(change_freq(m_effect->early_damping(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDAMP:
m_effect->set_late_damping(change_freq(m_effect->late_damping(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LPDELAY:
m_effect->set_late_predelay(change_ms(m_effect->late_predelay(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDECAY:
m_effect->set_late_global_decay(change_decay(m_effect->late_global_decay(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LSPIN:
m_effect->set_late_spin(change_spin(m_effect->late_spin(), false, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case ETAP:
if(m_effect->early_tap_setup() != 0) {
m_effect->set_early_tap_setup(m_effect->early_tap_setup() - 1);
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
}
return true;
}
break;
}
case IPT_UI_RIGHT: {
switch(uintptr_t(ev->itemref)) {
case MODE:
m_effect->set_mode(1);
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case PRESET:
if(m_preset != audio_effect_reverb::preset_count() - 1)
m_preset ++;
reset(reset_options::REMEMBER_POSITION);
return true;
case DRYL:
m_effect->set_dry_level(change_percent(m_effect->dry_level(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case EL:
m_effect->set_early_level(change_percent(m_effect->early_level(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LL:
m_effect->set_late_level(change_percent(m_effect->late_level(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case E2LL:
m_effect->set_early_to_late_level(change_percent(m_effect->early_to_late_level(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case ERS:
m_effect->set_early_room_size(change_percent(m_effect->early_room_size(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LRS:
m_effect->set_late_room_size(change_percent(m_effect->late_room_size(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case SW:
m_effect->set_stereo_width(change_percent(m_effect->stereo_width(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDIFF:
m_effect->set_late_diffusion(change_percent(m_effect->late_diffusion(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LWANDER:
m_effect->set_late_wander(change_percent(m_effect->late_wander(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case EDAMP:
m_effect->set_early_damping(change_freq(m_effect->early_damping(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDAMP:
m_effect->set_late_damping(change_freq(m_effect->late_damping(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LPDELAY:
m_effect->set_late_predelay(change_ms(m_effect->late_predelay(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDECAY:
m_effect->set_late_global_decay(change_decay(m_effect->late_global_decay(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LSPIN:
m_effect->set_late_spin(change_spin(m_effect->late_spin(), true, shift_pressed, ctrl_pressed, alt_pressed));
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case ETAP:
if(m_effect->early_tap_setup() != audio_effect_reverb::early_tap_setup_count() - 1) {
m_effect->set_early_tap_setup(m_effect->early_tap_setup() + 1);
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
}
return true;
}
break;
}
case IPT_UI_CLEAR: {
switch(uintptr_t(ev->itemref)) {
case MODE:
m_effect->reset_mode();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case DRYL:
m_effect->reset_dry_level();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case EL:
m_effect->reset_early_level();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LL:
m_effect->reset_late_level();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case E2LL:
m_effect->reset_early_to_late_level();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case ERS:
m_effect->reset_early_room_size();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LRS:
m_effect->reset_late_room_size();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case SW:
m_effect->reset_stereo_width();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDIFF:
m_effect->reset_late_diffusion();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LWANDER:
m_effect->reset_late_wander();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case EDAMP:
m_effect->reset_early_damping();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDAMP:
m_effect->reset_late_damping();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LPDELAY:
m_effect->reset_late_predelay();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LDECAY:
m_effect->reset_late_global_decay();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case LSPIN:
m_effect->reset_late_spin();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
case ETAP:
m_effect->reset_early_tap_setup();
if(m_chain == 0xffff)
machine().sound().default_effect_changed(m_entry);
reset(reset_options::REMEMBER_POSITION);
return true;
}
break;
}
}
return false;
}
std::string menu_audio_effect_reverb::format_percent(double val)
{
return util::string_format("%d%", u32(val));
}
std::string menu_audio_effect_reverb::format_freq(double val)
{
return util::string_format("%dHz", u32(val+0.5));
}
std::string menu_audio_effect_reverb::format_ms(double val)
{
return util::string_format("%5.1fms", val);
}
std::string menu_audio_effect_reverb::format_decay(double val)
{
return util::string_format("%5.2fs", val);
}
std::string menu_audio_effect_reverb::format_spin(double val)
{
return util::string_format("%3.2fHz", val);
}
u32 menu_audio_effect_reverb::flag_percent(double val, bool isset)
{
u32 flag = 0;
if(!isset)
flag |= FLAG_INVERT;
if(val > 0)
flag |= FLAG_LEFT_ARROW;
if(val < 100)
flag |= FLAG_RIGHT_ARROW;
return flag;
}
u32 menu_audio_effect_reverb::flag_freq(double val, bool isset)
{
u32 flag = 0;
if(!isset)
flag |= FLAG_INVERT;
if(val > 100)
flag |= FLAG_LEFT_ARROW;
if(val < 16000)
flag |= FLAG_RIGHT_ARROW;
return flag;
}
u32 menu_audio_effect_reverb::flag_ms(double val, bool isset)
{
u32 flag = 0;
if(!isset)
flag |= FLAG_INVERT;
if(val > 0)
flag |= FLAG_LEFT_ARROW;
if(val < 200)
flag |= FLAG_RIGHT_ARROW;
return flag;
}
u32 menu_audio_effect_reverb::flag_decay(double val, bool isset)
{
u32 flag = 0;
if(!isset)
flag |= FLAG_INVERT;
if(val > 0.1)
flag |= FLAG_LEFT_ARROW;
if(val < 30)
flag |= FLAG_RIGHT_ARROW;
return flag;
}
u32 menu_audio_effect_reverb::flag_spin(double val, bool isset)
{
u32 flag = 0;
if(!isset)
flag |= FLAG_INVERT;
if(val > 0)
flag |= FLAG_LEFT_ARROW;
if(val < 5)
flag |= FLAG_RIGHT_ARROW;
return flag;
}
double menu_audio_effect_reverb::change_percent(double val, bool inc, bool shift, bool ctrl, bool alt)
{
double step = alt ? 100 : ctrl ? 20 : shift ? 1 : 5;
if(inc)
val = std::min(100.0, val + step);
else
val = std::max(0.0, val - step);
return val;
}
double menu_audio_effect_reverb::change_freq(double val, bool inc, bool shift, bool ctrl, bool alt)
{
double step = alt ? 16000 : ctrl ? 20 : shift ? 1 : 5;
if(val >= 10000)
step *= 100;
else if(val >= 500)
step *= 50;
else if(val >= 250)
step *= 20;
else if(val >= 1000)
step *= 10;
else if(val >= 500)
step *= 5;
else if(val >= 250)
step *= 2;
if(inc)
val = std::min(16000.0, val + step);
else
val = std::max(100.0, val - step);
return val;
}
double menu_audio_effect_reverb::change_ms(double val, bool inc, bool shift, bool ctrl, bool alt)
{
double step = alt ? 200 : ctrl ? 10 : shift ? 0.1 : 1;
if(inc)
val = std::min(200.0, val + step);
else
val = std::max(0.0, val - step);
val = u32(val * 10 + 0.5) / 10.0;
return val;
}
double menu_audio_effect_reverb::change_decay(double val, bool inc, bool shift, bool ctrl, bool alt)
{
double step = alt ? 30 : ctrl ? 1 : shift ? 0.01 : 0.1;
if(inc)
val = std::min(30.0, val + step);
else
val = std::max(0.1, val - step);
val = u32(val * 100 + 0.5) / 100.0;
return val;
}
double menu_audio_effect_reverb::change_spin(double val, bool inc, bool shift, bool ctrl, bool alt)
{
double step = alt ? 5 : ctrl ? 1 : shift ? 0.01 : 0.1;
if(inc)
val = std::min(5.0, val + step);
else
val = std::max(0.0, val - step);
val = u32(val * 100 + 0.5) / 100.0;
return val;
}
void menu_audio_effect_reverb::populate()
{
item_append(_(audio_effect::effect_names[audio_effect::REVERB]), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
item_append(_("Mode"), m_effect->mode() ? _("Active") : _("Bypass"), flag_mode(), (void *)MODE);
item_append(_("Load preset"), audio_effect_reverb::preset_name(m_preset), flag_preset(), (void *)PRESET);
item_append(_("Dry level"), format_percent(m_effect->dry_level()), flag_percent(m_effect->dry_level(), m_effect->isset_dry_level()), (void *)DRYL);
item_append(_("Stereo width"), format_percent(m_effect->stereo_width()), flag_percent(m_effect->stereo_width(), m_effect->isset_stereo_width()), (void *)SW);
item_append(_("Early Reflections"), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
item_append(_("Room size"), format_percent(m_effect->early_room_size()), flag_percent(m_effect->early_room_size(), m_effect->isset_early_room_size()), (void *)ERS);
item_append(_("Tap setup"), audio_effect_reverb::early_tap_setup_name(m_effect->early_tap_setup()), flag_tap_setup(), (void *)ETAP);
item_append(_("Damping"), format_freq(m_effect->early_damping()), flag_percent(m_effect->early_damping(), m_effect->isset_early_damping()), (void *)EDAMP);
item_append(_("Level"), format_percent(m_effect->early_level()), flag_percent(m_effect->early_level(), m_effect->isset_early_level()), (void *)EL);
item_append(_("Send to Late"), format_percent(m_effect->early_to_late_level()), flag_percent(m_effect->early_to_late_level(), m_effect->isset_early_to_late_level()), (void *)E2LL);
item_append(_("Late Reflections"), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
item_append(_("Room size"), format_percent(m_effect->late_room_size()), flag_percent(m_effect->late_room_size(), m_effect->isset_late_room_size()), (void *)LRS);
item_append(_("Damping"), format_freq(m_effect->late_damping()), flag_percent(m_effect->late_damping(), m_effect->isset_late_damping()), (void *)LDAMP);
item_append(_("Pre-delay"), format_ms(m_effect->late_predelay()), flag_percent(m_effect->late_predelay(), m_effect->isset_late_predelay()), (void *)LPDELAY);
item_append(_("Diffusion"), format_percent(m_effect->late_diffusion()), flag_percent(m_effect->late_diffusion(), m_effect->isset_late_diffusion()), (void *)LDIFF);
item_append(_("Wander"), format_percent(m_effect->late_wander()), flag_percent(m_effect->late_wander(), m_effect->isset_late_wander()), (void *)LWANDER);
item_append(_("Decay"), format_decay(m_effect->late_global_decay()), flag_decay(m_effect->late_global_decay(), m_effect->isset_late_global_decay()), (void *)LDECAY);
item_append(_("Spin"), format_spin(m_effect->late_spin()), flag_spin(m_effect->late_spin(), m_effect->isset_late_spin()), (void *)LSPIN);
item_append(_("Level"), format_percent(m_effect->late_level()), flag_percent(m_effect->late_level(), m_effect->isset_late_level()), (void *)LL);
item_append(menu_item_type::SEPARATOR);
}
void menu_audio_effect_reverb::recompute_metrics(uint32_t width, uint32_t height, float aspect)
{
menu::recompute_metrics(width, height, aspect);
}
void menu_audio_effect_reverb::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
{
}
void menu_audio_effect_reverb::menu_activated()
{
// scripts or the other form of the menu could have changed something in the mean time
reset(reset_options::REMEMBER_POSITION);
}
void menu_audio_effect_reverb::menu_deactivated()
{
}
u32 menu_audio_effect_reverb::flag_mode() const
{
u32 flag = 0;
if(!m_effect->isset_mode())
flag |= FLAG_INVERT;
if(m_effect->mode())
flag |= FLAG_LEFT_ARROW;
else
flag |= FLAG_RIGHT_ARROW;
return flag;
}
u32 menu_audio_effect_reverb::flag_tap_setup() const
{
u32 flag = 0;
if(!m_effect->isset_early_tap_setup())
flag |= FLAG_INVERT;
if(m_effect->early_tap_setup() != 0)
flag |= FLAG_LEFT_ARROW;
if(m_effect->early_tap_setup() != audio_effect_reverb::early_tap_setup_count() - 1)
flag |= FLAG_RIGHT_ARROW;
return flag;
}
u32 menu_audio_effect_reverb::flag_preset() const
{
u32 flag = 0;
if(m_preset != 0)
flag |= FLAG_LEFT_ARROW;
if(m_preset != audio_effect_reverb::preset_count() - 1)
flag |= FLAG_RIGHT_ARROW;
return flag;
}
}

View File

@ -0,0 +1,88 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
ui/audio_effect_reverb.h
Reverb configuration
***************************************************************************/
#ifndef MAME_FRONTEND_UI_AUDIO_EFFECT_REVERB_H
#define MAME_FRONTEND_UI_AUDIO_EFFECT_REVERB_H
#pragma once
#include "ui/menu.h"
class audio_effect_reverb;
namespace ui {
class menu_audio_effect_reverb : public menu
{
public:
menu_audio_effect_reverb(mame_ui_manager &mui, render_container &container, u16 chain, u16 entry, audio_effect *effect);
virtual ~menu_audio_effect_reverb() override;
protected:
virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override;
virtual void custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
virtual void menu_activated() override;
virtual void menu_deactivated() override;
private:
enum {
MODE,
PRESET,
DRYL,
EL,
LL,
E2LL,
SW,
EDAMP,
ERS,
ETAP,
LDAMP,
LDIFF,
LPDELAY,
LRS,
LDECAY,
LSPIN,
LWANDER
};
u16 m_chain, m_entry;
u32 m_preset;
audio_effect_reverb *m_effect;
virtual void populate() override;
virtual bool handle(event const *ev) override;
static std::string format_percent(double val);
static std::string format_freq(double val);
static std::string format_ms(double val);
static std::string format_decay(double val);
static std::string format_spin(double val);
u32 flag_mode() const;
u32 flag_tap_setup() const;
u32 flag_preset() const;
static u32 flag_percent(double val, bool isset);
static u32 flag_freq(double val, bool isset);
static u32 flag_ms(double val, bool isset);
static u32 flag_decay(double val, bool isset);
static u32 flag_spin(double val, bool isset);
static double change_percent(double val, bool inc, bool shift, bool ctrl, bool alt);
static double change_freq(double val, bool inc, bool shift, bool ctrl, bool alt);
static double change_ms(double val, bool inc, bool shift, bool ctrl, bool alt);
static double change_decay(double val, bool inc, bool shift, bool ctrl, bool alt);
static double change_spin(double val, bool inc, bool shift, bool ctrl, bool alt);
};
} // namespace ui
#endif // MAME_FRONTEND_UI_AUDIO_EFFECT_REVERB_H

View File

@ -15,6 +15,7 @@
#include "audio_effect_compressor.h" #include "audio_effect_compressor.h"
#include "audio_effect_eq.h" #include "audio_effect_eq.h"
#include "audio_effect_filter.h" #include "audio_effect_filter.h"
#include "audio_effect_reverb.h"
#include "ui/ui.h" #include "ui/ui.h"
@ -106,6 +107,10 @@ bool menu_audio_effects::handle(event const *ev)
case audio_effect::FILTER: case audio_effect::FILTER:
menu::stack_push<menu_audio_effect_filter>(ui(), container(), chain, entry, eff); menu::stack_push<menu_audio_effect_filter>(ui(), container(), chain, entry, eff);
break; break;
case audio_effect::REVERB:
menu::stack_push<menu_audio_effect_reverb>(ui(), container(), chain, entry, eff);
break;
} }
return true; return true;
} }

View File

@ -599,7 +599,7 @@ void menu_audio_mixer::populate()
} }
for(const auto &cmap : omap.m_channel_mappings) { for(const auto &cmap : omap.m_channel_mappings) {
const auto &node = find_node(cmap.m_node); const auto &node = find_node(cmap.m_node);
std::string guest_channel = omap.m_dev->get_position_name(cmap.m_guest_channel); std::string guest_channel = omap.m_dev->get_position(cmap.m_guest_channel).name();
if(curline == cursel_line && m_current_group == GRP_GUEST_CHANNEL) if(curline == cursel_line && m_current_group == GRP_GUEST_CHANNEL)
guest_channel = u8"\u25c4" + guest_channel + u8"\u25ba"; guest_channel = u8"\u25c4" + guest_channel + u8"\u25ba";

View File

@ -903,7 +903,7 @@ void atarigt_state::atarigt_stereo(machine_config &config)
// based on dedicated cabinet configuration; // based on dedicated cabinet configuration;
// 'universal' kit supports mono and stereo, with/without subwoofer. // 'universal' kit supports mono and stereo, with/without subwoofer.
SPEAKER(config, "speaker", 2).front(); SPEAKER(config, "speaker", 2).front();
SPEAKER(config, "subwoofer").front_floor(); // Next to the coin door at dedicated cabinet, just silence for now (not implemented) SPEAKER(config, "subwoofer").lfe(); // Next to the coin door at dedicated cabinet, just silence for now (not implemented)
// TODO: correct? sound board has only 1 DAC populated. // TODO: correct? sound board has only 1 DAC populated.
m_cage->add_route(0, "speaker", 1.0, 1); m_cage->add_route(0, "speaker", 1.0, 1);
@ -925,7 +925,7 @@ void atarigt_state::tmek(machine_config &config)
// 5 Channel output (4 Channel input connected to Quad Amp PCB) // 5 Channel output (4 Channel input connected to Quad Amp PCB)
SPEAKER(config, "speaker", 4).front().headrest_left(2).headrest_right(3); SPEAKER(config, "speaker", 4).front().headrest_left(2).headrest_right(3);
//SPEAKER(config, "subwoofer").seat(); Not implemented, Quad Amp PCB output; //SPEAKER(config, "subwoofer").lfe(); Not implemented, Quad Amp PCB output;
m_cage->set_speedup(0x4fad); m_cage->set_speedup(0x4fad);
m_cage->add_route(0, "speaker", 1.0, 1); // Foward Right m_cage->add_route(0, "speaker", 1.0, 1); // Foward Right

View File

@ -761,7 +761,7 @@ void metalmx_state::metalmx(machine_config &config)
// TODO: copied from atarigt.cpp; Same configurations as T-Mek? // TODO: copied from atarigt.cpp; Same configurations as T-Mek?
// 5 Channel output (4 Channel input connected to Quad Amp PCB) // 5 Channel output (4 Channel input connected to Quad Amp PCB)
SPEAKER(config, "speaker", 4).front().headrest_left(2).headrest_right(3); SPEAKER(config, "speaker", 4).front().headrest_left(2).headrest_right(3);
//SPEAKER(config, "subwoofer").seat(); Not implemented, Quad Amp PCB output; //SPEAKER(config, "subwoofer").lfe(); Not implemented, Quad Amp PCB output;
ATARI_CAGE(config, m_cage, 0); ATARI_CAGE(config, m_cage, 0);
m_cage->set_speedup(0); // TODO: speedup address m_cage->set_speedup(0); // TODO: speedup address

View File

@ -2171,7 +2171,7 @@ void seattle_state::sfrush(machine_config &config)
// 5 Channel output (4 Channel input connected to Quad Amp PCB) // 5 Channel output (4 Channel input connected to Quad Amp PCB)
SPEAKER(config, "speaker", 4).corners(); SPEAKER(config, "speaker", 4).corners();
//SPEAKER(config, "subwoofer").seat(); Not implemented, Quad Amp PCB output; //SPEAKER(config, "subwoofer").lfe(); Not implemented, Quad Amp PCB output;
ATARI_CAGE_SEATTLE(config, m_cage, 0); ATARI_CAGE_SEATTLE(config, m_cage, 0);
m_cage->set_speedup(0x5236); m_cage->set_speedup(0x5236);
@ -2201,7 +2201,7 @@ void seattle_state::sfrushrk(machine_config &config)
// 5 Channel output (4 Channel input connected to Quad Amp PCB) // 5 Channel output (4 Channel input connected to Quad Amp PCB)
SPEAKER(config, "speaker", 4).corners(); SPEAKER(config, "speaker", 4).corners();
//SPEAKER(config, "subwoofer").seat(); Not implemented, Quad Amp PCB output; //SPEAKER(config, "subwoofer").lfe(); Not implemented, Quad Amp PCB output;
ATARI_CAGE_SEATTLE(config, m_cage, 0); ATARI_CAGE_SEATTLE(config, m_cage, 0);
m_cage->set_speedup(0x5329); m_cage->set_speedup(0x5329);

View File

@ -3846,7 +3846,7 @@ void namcos22s_state::airco22b(machine_config &config)
{ {
namcos22s(config); namcos22s(config);
SPEAKER(config, "bodysonic").backrest(); SPEAKER(config, "bodysonic").lfe();
m_c352->add_route(2, "bodysonic", 0.50); // to subwoofer behind back m_c352->add_route(2, "bodysonic", 0.50); // to subwoofer behind back
} }
@ -3892,7 +3892,7 @@ void namcos22s_state::tokyowar(machine_config &config)
{ {
namcos22s(config); namcos22s(config);
SPEAKER(config, "vibration").seat(); SPEAKER(config, "vibration").lfe();
SPEAKER(config, "seat").headrest_center(); SPEAKER(config, "seat").headrest_center();
m_c352->add_route(2, "vibration", 0.5); // to "bass shaker" m_c352->add_route(2, "vibration", 0.5); // to "bass shaker"

View File

@ -394,7 +394,7 @@ void s11b_state::s11b_jokerz(machine_config &config)
m_cvsd_filter2->add_route(ALL_OUTPUTS, m_ps88, (0.25*4.0), 1); m_cvsd_filter2->add_route(ALL_OUTPUTS, m_ps88, (0.25*4.0), 1);
m_pia34->ca2_handler().set(m_ps88, FUNC(pinsnd88_device::resetq_w)); m_pia34->ca2_handler().set(m_ps88, FUNC(pinsnd88_device::resetq_w));
m_ps88->syncq_cb().set(m_pia34, FUNC(pia6821_device::ca1_w)); // the sync connection comes from sound connector pin 16 to MCA1, not the usual pin 12 to MCB1 m_ps88->syncq_cb().set(m_pia34, FUNC(pia6821_device::ca1_w)); // the sync connection comes from sound connector pin 16 to MCA1, not the usual pin 12 to MCB1
SPEAKER(config, "cabinet").front_floor(); // the cabinet speaker is aimed down underneath the pinball table itself SPEAKER(config, "cabinet").set_position(0, 0.0, -0.5, 1.0); // the cabinet speaker is aimed down underneath the pinball table itself
SPEAKER(config, "backbox").front_center(); // the backbox speakers are roughly level with the user, but farther in front of them than the cabinet SPEAKER(config, "backbox").front_center(); // the backbox speakers are roughly level with the user, but farther in front of them than the cabinet
m_ps88->add_route(0, "cabinet", 1.0); m_ps88->add_route(0, "cabinet", 1.0);
m_ps88->add_route(1, "backbox", 1.0); m_ps88->add_route(1, "backbox", 1.0);

View File

@ -974,7 +974,7 @@ void ninjaw_state::ninjaw(machine_config &config)
/* sound hardware */ /* sound hardware */
SPEAKER(config, "speaker", 2).front(); SPEAKER(config, "speaker", 2).front();
SPEAKER(config, "subwoofer").seat(); SPEAKER(config, "subwoofer").lfe();
ym2610_device &ymsnd(YM2610(config, "ymsnd", 16000000/2)); ym2610_device &ymsnd(YM2610(config, "ymsnd", 16000000/2));
ymsnd.irq_handler().set_inputline("audiocpu", 0); ymsnd.irq_handler().set_inputline("audiocpu", 0);
@ -1079,7 +1079,7 @@ void ninjaw_state::darius2(machine_config &config)
/* sound hardware */ /* sound hardware */
SPEAKER(config, "speaker", 2).front(); SPEAKER(config, "speaker", 2).front();
SPEAKER(config, "subwoofer").seat(); SPEAKER(config, "subwoofer").lfe();
ym2610_device &ymsnd(YM2610(config, "ymsnd", 16000000/2)); ym2610_device &ymsnd(YM2610(config, "ymsnd", 16000000/2));
ymsnd.irq_handler().set_inputline("audiocpu", 0); ymsnd.irq_handler().set_inputline("audiocpu", 0);

View File

@ -3221,7 +3221,7 @@ void contcirc_state::contcirc(machine_config &config) //OSC: 26.686, 24.000, 16.
/* sound hardware */ /* sound hardware */
SPEAKER(config, "front").front_center(); SPEAKER(config, "front").front_center();
SPEAKER(config, "rear").rear_center(); SPEAKER(config, "rear").rear_center();
SPEAKER(config, "subwoofer").set_position(0, 0.0, 0.0, 0.0); // FIXME: where is this speaker located? SPEAKER(config, "subwoofer").lfe();
ym2610_device &ymsnd(YM2610(config, "ymsnd", XTAL(16'000'000)/2)); // 8 MHz ym2610_device &ymsnd(YM2610(config, "ymsnd", XTAL(16'000'000)/2)); // 8 MHz
ymsnd.irq_handler().set_inputline(m_audiocpu, 0); ymsnd.irq_handler().set_inputline(m_audiocpu, 0);
@ -3280,7 +3280,7 @@ void chasehq_state::chasehq(machine_config &config) //OSC: 26.686, 24.000, 16.00
/* sound hardware */ /* sound hardware */
SPEAKER(config, "front").front_center(); SPEAKER(config, "front").front_center();
SPEAKER(config, "rear").rear_center(); SPEAKER(config, "rear").rear_center();
SPEAKER(config, "subwoofer").set_position(0, 0.0, 0.0, 0.0); // FIXME: where is this speaker located? SPEAKER(config, "subwoofer").lfe();
ym2610_device &ymsnd(YM2610(config, "ymsnd", XTAL(16'000'000)/2)); // 8 MHz ym2610_device &ymsnd(YM2610(config, "ymsnd", XTAL(16'000'000)/2)); // 8 MHz
ymsnd.irq_handler().set_inputline(m_audiocpu, 0); ymsnd.irq_handler().set_inputline(m_audiocpu, 0);
@ -3539,7 +3539,7 @@ void nightstr_state::nightstr(machine_config &config) //OSC: 26.686, 24.000, 16.
/* sound hardware */ /* sound hardware */
SPEAKER(config, "front").front_center(); SPEAKER(config, "front").front_center();
SPEAKER(config, "rear").rear_center(); SPEAKER(config, "rear").rear_center();
SPEAKER(config, "subwoofer").set_position(0, 0.0, 0.0, 0.0); // FIXME: where is this located in the cabinet? SPEAKER(config, "subwoofer").lfe();
ym2610_device &ymsnd(YM2610(config, "ymsnd", XTAL(16'000'000)/2)); // 8 MHz ym2610_device &ymsnd(YM2610(config, "ymsnd", XTAL(16'000'000)/2)); // 8 MHz
ymsnd.irq_handler().set_inputline(m_audiocpu, 0); ymsnd.irq_handler().set_inputline(m_audiocpu, 0);

View File

@ -1155,7 +1155,7 @@ void dendego_state::dendego(machine_config &config)
m_screen->set_screen_update(FUNC(dendego_state::screen_update_dendego)); m_screen->set_screen_update(FUNC(dendego_state::screen_update_dendego));
/* sound hardware */ /* sound hardware */
SPEAKER(config, "vibration").seat(); SPEAKER(config, "vibration").lfe();
/* clock frequency & pin 7 not verified */ /* clock frequency & pin 7 not verified */
OKIM6295(config, "oki", 1056000, okim6295_device::PIN7_HIGH).add_route(ALL_OUTPUTS, "vibration", 0.20); OKIM6295(config, "oki", 1056000, okim6295_device::PIN7_HIGH).add_route(ALL_OUTPUTS, "vibration", 0.20);

View File

@ -630,7 +630,7 @@ void warriorb_state::darius2d(machine_config &config)
// sound hardware // sound hardware
SPEAKER(config, "speaker", 2).front(); SPEAKER(config, "speaker", 2).front();
SPEAKER(config, "subwoofer").seat(); SPEAKER(config, "subwoofer").lfe();
ym2610_device &ymsnd(YM2610(config, "ymsnd", 16_MHz_XTAL / 2)); ym2610_device &ymsnd(YM2610(config, "ymsnd", 16_MHz_XTAL / 2));
ymsnd.irq_handler().set_inputline("audiocpu", 0); ymsnd.irq_handler().set_inputline("audiocpu", 0);

View File

@ -0,0 +1,49 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#include "emu.h"
#include "audio.h"
const osd::channel_position osd::channel_position::UNKNOWN(0.0, 0.0, 0.0);
const osd::channel_position osd::channel_position::ONREQ (0.0, 0.0, 10.0);
const osd::channel_position osd::channel_position::LFE (0.0, 0.0, 11.0);
bool osd::channel_position::is_lfe() const { return *this == LFE; }
bool osd::channel_position::is_onreq() const { return *this == ONREQ; }
bool osd::channel_position::is_unknown() const { return *this == UNKNOWN; }
const osd::channel_position osd::channel_position::FC ( 0.0, 0.0, 1.0);
const osd::channel_position osd::channel_position::FL (-0.2, 0.0, 1.0);
const osd::channel_position osd::channel_position::FR ( 0.2, 0.0, 1.0);
const osd::channel_position osd::channel_position::RC ( 0.0, 0.0, -0.5);
const osd::channel_position osd::channel_position::RL (-0.2, 0.0, -0.5);
const osd::channel_position osd::channel_position::RR ( 0.2, 0.0, -0.5);
const osd::channel_position osd::channel_position::HC ( 0.0, 0.0, -0.1);
const osd::channel_position osd::channel_position::HL (-0.1, 0.0, -0.1);
const osd::channel_position osd::channel_position::HR ( 0.1, 0.0, -0.1);
const osd::channel_position osd::channel_position::BACKREST( 0.0, -0.2, 0.1);
const osd::detail::position_name_mapping osd::detail::position_name_mappings[] = {
{ channel_position::FC, "Front center" },
{ channel_position::FL, "Front left" },
{ channel_position::FR, "Front right" },
{ channel_position::RC, "Rear center" },
{ channel_position::RL, "Rear left" },
{ channel_position::RR, "Rear right" },
{ channel_position::HC, "Headrest center" },
{ channel_position::HL, "Headrest left" },
{ channel_position::HR, "Headrest right" },
{ channel_position::BACKREST, "Backrest" },
{ channel_position::LFE, "Subwoofer" },
{ channel_position::ONREQ, "Auxiliary" },
{ channel_position::UNKNOWN, "Unknown" }
};
std::string osd::channel_position::name() const
{
for(unsigned int i=0; i != sizeof(detail::position_name_mappings)/sizeof(detail::position_name_mappings[0]); i++)
if(*this == detail::position_name_mappings[i].m_pos)
return detail::position_name_mappings[i].m_name;
return util::string_format("[%f %f %f]", m_x, m_y, m_z);
}

View File

@ -16,6 +16,57 @@
namespace osd { namespace osd {
struct channel_position {
// Special positions
// Position is unknown, placed in the middle
static const struct channel_position UNKNOWN;
// This channel should only be mapped explicitely through a channel mapping (on request)
static const struct channel_position ONREQ;
// This channel is a LFE
static const struct channel_position LFE;
// Standard positions
static const struct channel_position FC;
static const struct channel_position FL;
static const struct channel_position FR;
static const struct channel_position RC;
static const struct channel_position RL;
static const struct channel_position RR;
static const struct channel_position HC;
static const struct channel_position HL;
static const struct channel_position HR;
static const struct channel_position BACKREST;
double m_x, m_y, m_z;
bool is_lfe() const;
bool is_onreq() const;
bool is_unknown() const;
channel_position() : channel_position(UNKNOWN) {}
channel_position(double x, double y, double z) : m_x(x), m_y(y), m_z(z) {}
channel_position(const channel_position &pos) : m_x(pos.m_x), m_y(pos.m_y), m_z(pos.m_z) {}
bool operator == (const channel_position &pos) const {
return pos.m_x == m_x && pos.m_y == m_y && pos.m_z == m_z;
}
std::string name() const;
};
namespace detail {
struct position_name_mapping {
struct channel_position m_pos;
const char *m_name;
};
extern const position_name_mapping position_name_mappings[];
};
struct audio_rate_range { struct audio_rate_range {
uint32_t m_default_rate; uint32_t m_default_rate;
uint32_t m_min_rate; uint32_t m_min_rate;
@ -41,7 +92,7 @@ struct audio_info {
uint32_t m_id; uint32_t m_id;
audio_rate_range m_rate; audio_rate_range m_rate;
std::vector<std::string> m_port_names; std::vector<std::string> m_port_names;
std::vector<std::array<double, 3> > m_port_positions; std::vector<channel_position> m_port_positions;
uint32_t m_sinks; uint32_t m_sinks;
uint32_t m_sources; uint32_t m_sources;

View File

@ -102,62 +102,62 @@ static const char *sMacChannelLabels[sMacChannelCount] =
// "Surround" channels are at X = -0.4 (left) and 0.4 (right). // "Surround" channels are at X = -0.4 (left) and 0.4 (right).
static const std::array<double,3> sChannelPositions[sMacChannelCount] = static const std::array<double,3> sChannelPositions[sMacChannelCount] =
{ {
{ 0.0, 0.0, 0.0 }, // unused osd::channel_position::UNKNOWN, // unused
{ -0.2, 0.0, 1.0 }, // Front Left osd::channel_position::FL, // Front Left
{ 0.2, 0.0, 1.0 }, // Front Right osd::channel_position::FR, // Front Right
{ 0.0, 0.0, 1.0 }, // Front Center osd::channel_position::FC, // Front Center
{ 0.0, -0.5, 0.0 }, // Low Frequency Effects osd::channel_position::LFE, // Low Frequency Effects
{ -0.2, 0.0, -0.5 }, // Rear Left osd::channel_position::RL, // Rear Left
{ 0.2, 0.0, -0.5 }, // Rear Right osd::channel_position::RR, // Rear Right
{ -0.1, 0.0, 1.0 }, // Front Left of Center osd::channel_position( -0.1, 0.0, 1.0 ), // Front Left of Center
{ 0.1, 0.0, 1.0 }, // Front Right of Center osd::channel_position( 0.1, 0.0, 1.0 ), // Front Right of Center
{ 0.0, 0.0, -1.0 }, // Rear Center osd::channel_position::RC, // Rear Center
{ -0.2, 0.0, 0.5 }, // Side Left osd::channel_position( -0.2, 0.0, 0.5 ), // Side Left
{ 0.2, 0.0, 0.5 }, // Side Right osd::channel_position( 0.2, 0.0, 0.5 ), // Side Right
{ 0.0, 0.5, -0.1 }, // Top Center osd::channel_position( 0.0, 0.5, -0.1 ), // Top Center
{ -0.2, 0.5, 1.0 }, // Top Front Left osd::channel_position( -0.2, 0.5, 1.0 ), // Top Front Left
{ 0.0, 0.5, 1.0 }, // Top Front Center osd::channel_position( 0.0, 0.5, 1.0 ), // Top Front Center
{ 0.2, 0.5, 1.0 }, // Top Front Right osd::channel_position( 0.2, 0.5, 1.0 ), // Top Front Right
{ -0.2, 0.5, -0.5 }, // Top Rear Left osd::channel_position( -0.2, 0.5, -0.5 ), // Top Rear Left
{ 0.2, 0.5, -0.5 }, // Top Rear Center osd::channel_position( 0.2, 0.5, -0.5 ), // Top Rear Center
{ 0.2, 0.5, -0.5 }, // Top Rear Right osd::channel_position( 0.2, 0.5, -0.5 ), // Top Rear Right
{ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN,
{ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN,
{ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN,
{ -0.4, 0.0, -0.5 }, // Rear Surround Left osd::channel_position( -0.4, 0.0, -0.5 ), // Rear Surround Left
{ 0.4, 0.0, -0.5 }, // Rear Surround Right osd::channel_position( 0.4, 0.0, -0.5 ), // Rear Surround Right
{ -0.4, 0.0, 1.0 }, // Left Wide osd::channel_position( -0.4, 0.0, 1.0 ), // Left Wide
{ 0.4, 0.0, 1.0 }, // Right Wide osd::channel_position( 0.4, 0.0, 1.0 ), // Right Wide
{ 0.0, -0.5, 0.0 }, // Low Frequency Effects 2 osd::channel_position::LFE, // Low Frequency Effects 2
{ -0.1, 0.0, -0.1 }, // Left Total osd::channel_position::HL, // Left Total
{ 0.1, 0.0, -0.1 }, // Right Total osd::channel_position::HR, // Right Total
{ 0.0, 0.0, 1.0 }, // Hearing Impaired osd::channel_position::FC, // Hearing Impaired
{ 0.0, 0.0, 1.0 }, // Narration osd::channel_position::FC, // Narration
{ 0.0, 0.0, 1.0 }, // Mono osd::channel_position::FC, // Mono
{ 0.0, 0.0, 1.0 }, // Dialog Centric Mix osd::channel_position::FC, // Dialog Centric Mix
{ 0.0, 0.0, -0.1 }, // Center Surround Direct osd::channel_position::HC, // Center Surround Direct
{ 0.0, 0.0, 0.0 }, // Haptic osd::channel_position::UNKNOWN, // Haptic
{ 0.0, 0.0, 0.0 }, // unused osd::channel_position::UNKNOWN, // unused
{ 0.0, 0.0, 0.0 }, // unused osd::channel_position::UNKNOWN, // unused
{ 0.0, 0.0, 0.0 }, // unused osd::channel_position::UNKNOWN, // unused
{ -0.2, 0.5, 0.0 }, // Left Top Middle osd::channel_position( -0.2, 0.5, 0.0 ), // Left Top Middle
{ 0.0, 0.0, 0.0 }, // unused osd::channel_position::UNKNOWN, // unused
{ 0.2, 0.5, 0.0 }, // Right Top Middle osd::channel_position( 0.2, 0.5, 0.0 ), // Right Top Middle
{ -0.2, 0.5, -0.5 }, // Left Top Rear osd::channel_position( -0.2, 0.5, -0.5 ), // Left Top Rear
{ 0.0, 0.5, -0.5 }, // Center Top Rear osd::channel_position( 0.0, 0.5, -0.5 ), // Center Top Rear
{ 0.2, 0.5, -0.5 }, // Right Top Rear osd::channel_position( 0.2, 0.5, -0.5 ), // Right Top Rear
{ -0.4, 0.0, -0.1 }, // Left Side Surround osd::channel_position( -0.4, 0.0, -0.1 ), // Left Side Surround
{ 0.4, 0.0, -0.1 }, // Right Side Surround osd::channel_position( 0.4, 0.0, -0.1 ), // Right Side Surround
{ -0.2, -0.5, 0.0 }, // Left Bottom osd::channel_position( -0.2, -0.5, 0.0 ), // Left Bottom
{ 0.2, -0.5, 0.0 }, // Right Bottom osd::channel_position( 0.2, -0.5, 0.0 ), // Right Bottom
{ 0.0, -0.5, 0.0 }, // Center Bottom osd::channel_position( 0.0, -0.5, 0.0 ), // Center Bottom
{ -0.4, 0.5, -0.1 }, // Left Top Surround osd::channel_position( -0.4, 0.5, -0.1 ), // Left Top Surround
{ 0.4, 0.5, -0.1 }, // Right Top Surround osd::channel_position( 0.4, 0.5, -0.1 ), // Right Top Surround
{ 0.0, 0.0, 0.0 }, // Low Frequency Effects 3 osd::channel_position::UNKNOWN, // Low Frequency Effects 3
{ -0.4, 0.0, -0.5 }, // Left Rear Surround osd::channel_position( -0.4, 0.0, -0.5 ), // Left Rear Surround
{ 0.4, 0.0, -0.5 }, // Right Rear Surround osd::channel_position( 0.4, 0.0, -0.5 ), // Right Rear Surround
{ -0.1, 0.0, 1.0 }, // Left Edge of Screen osd::channel_position( -0.1, 0.0, 1.0 ), // Left Edge of Screen
{ 0.1, 0.0, 1.0 } // Right Edge of Screen osd::channel_position( 0.1, 0.0, 1.0 ) // Right Edge of Screen
}; };
struct coreaudio_device struct coreaudio_device
@ -1064,7 +1064,7 @@ void sound_coreaudio::build_device_list()
{ {
std::string chLabel = "Channel " + std::to_string(desc + 1); std::string chLabel = "Channel " + std::to_string(desc + 1);
node.m_port_names.push_back(chLabel); node.m_port_names.push_back(chLabel);
node.m_port_positions.emplace_back(std::array<double, 3>({0.0, 0.0, 1.0})); node.m_port_positions.emplace_back(osd::channel_position::FC);
} }
else else
{ {

View File

@ -48,25 +48,25 @@ char const *const f_speaker_names[] ={
"TBC", // SPEAKER_TOP_BACK_CENTER "TBC", // SPEAKER_TOP_BACK_CENTER
"TBR" }; // SPEAKER_TOP_BACK_RIGHT "TBR" }; // SPEAKER_TOP_BACK_RIGHT
std::array<double, 3> const f_speaker_positions[] = { osd::channel_position const f_speaker_positions[] = {
{ -0.2, 0.0, 1.0 }, // SPEAKER_FRONT_LEFT osd::channel_position::FL, // SPEAKER_FRONT_LEFT
{ 0.2, 0.0, 1.0 }, // SPEAKER_FRONT_RIGHT osd::channel_position::FR, // SPEAKER_FRONT_RIGHT
{ 0.0, 0.0, 1.0 }, // SPEAKER_FRONT_CENTER osd::channel_position::FC, // SPEAKER_FRONT_CENTER
{ 0.0, -0.5, 1.0 }, // SPEAKER_LOW_FREQUENCY osd::channel_position::LFE, // SPEAKER_LOW_FREQUENCY
{ -0.2, 0.0, -0.5 }, // SPEAKER_BACK_LEFT osd::channel_position::RL, // SPEAKER_BACK_LEFT
{ 0.2, 0.0, -0.5 }, // SPEAKER_BACK_RIGHT osd::channel_position::RR, // SPEAKER_BACK_RIGHT
{ -0.1, 0.0, 1.0 }, // SPEAKER_FRONT_LEFT_OF_CENTER osd::channel_position( -0.1, 0.0, 1.0 ), // SPEAKER_FRONT_LEFT_OF_CENTER
{ 0.1, 0.0, 1.0 }, // SPEAKER_FRONT_RIGHT_OF_CENTER osd::channel_position( 0.1, 0.0, 1.0 ), // SPEAKER_FRONT_RIGHT_OF_CENTER
{ 0.0, 0.0, -0.5 }, // SPEAKER_BACK_CENTER osd::channel_position::RC, // SPEAKER_BACK_CENTER
{ -0.2, 0.0, 0.0 }, // SPEAKER_SIDE_LEFT osd::channel_position( -0.2, 0.0, 0.0 ), // SPEAKER_SIDE_LEFT
{ 0.2, 0.0, 0.0 }, // SPEAKER_SIDE_RIGHT osd::channel_position( 0.2, 0.0, 0.0 ), // SPEAKER_SIDE_RIGHT
{ 0.0, 0.5, 0.0 }, // SPEAKER_TOP_CENTER osd::channel_position( 0.0, 0.5, 0.0 ), // SPEAKER_TOP_CENTER
{ -0.2, 0.5, 1.0 }, // SPEAKER_TOP_FRONT_LEFT osd::channel_position( -0.2, 0.5, 1.0 ), // SPEAKER_TOP_FRONT_LEFT
{ 0.0, 0.5, 1.0 }, // SPEAKER_TOP_FRONT_CENTER osd::channel_position( 0.0, 0.5, 1.0 ), // SPEAKER_TOP_FRONT_CENTER
{ 0.2, 0.5, 1.0 }, // SPEAKER_TOP_FRONT_RIGHT osd::channel_position( 0.2, 0.5, 1.0 ), // SPEAKER_TOP_FRONT_RIGHT
{ -0.2, 0.5, -0.5 }, // SPEAKER_TOP_BACK_LEFT osd::channel_position( -0.2, 0.5, -0.5 ), // SPEAKER_TOP_BACK_LEFT
{ 0.0, 0.5, -0.5 }, // SPEAKER_TOP_BACK_CENTER osd::channel_position( 0.0, 0.5, -0.5 ), // SPEAKER_TOP_BACK_CENTER
{ 0.2, 0.5, -0.5 } }; // SPEAKER_TOP_BACK_RIGHT osd::channel_position( 0.2, 0.5, -0.5 ) }; // SPEAKER_TOP_BACK_RIGHT
} // anonymous namespace } // anonymous namespace

View File

@ -101,17 +101,17 @@ int sound_pa::init(osd_interface &osd, osd_options const &options)
enum { FL, FR, FC, LFE, BL, BR, BC, SL, SR, AUX }; enum { FL, FR, FC, LFE, BL, BR, BC, SL, SR, AUX };
static const char *const posname[10] = { "FL", "FR", "FC", "LFE", "BL", "BR", "BC", "SL", "SR", "AUX" }; static const char *const posname[10] = { "FL", "FR", "FC", "LFE", "BL", "BR", "BC", "SL", "SR", "AUX" };
static const std::array<double, 3> pos3d[10] = { static const osd::channel_position pos3d[10] = {
{ -0.2, 0.0, 1.0 }, osd::channel_position::FL,
{ 0.2, 0.0, 1.0 }, osd::channel_position::FR,
{ 0.0, 0.0, 1.0 }, osd::channel_position::FC,
{ 0.0, -0.5, 1.0 }, osd::channel_position::LFE,
{ -0.2, 0.0, -0.5 }, osd::channel_position::RL,
{ 0.2, 0.0, -0.5 }, osd::channel_position::RR,
{ 0.0, 0.0, -0.5 }, osd::channel_position::RC,
{ -0.2, 0.0, 0.0 }, osd::channel_position(-0.2, 0.0, 0.0),
{ 0.2, 0.0, 0.0 }, osd::channel_position( 0.2, 0.0, 0.0),
{ 0.0, 0.0, 10.0 }, osd::channel_position::ONREQ
}; };
static const uint32_t positions[9][9] = { static const uint32_t positions[9][9] = {

View File

@ -53,7 +53,7 @@ public:
private: private:
struct position_info { struct position_info {
uint32_t m_position; uint32_t m_position;
std::array<double, 3> m_coords; osd::channel_position m_coords;
}; };
static const position_info position_infos[]; static const position_info position_infos[];
@ -73,7 +73,7 @@ private:
uint32_t m_sinks, m_sources; uint32_t m_sinks, m_sources;
std::vector<uint32_t> m_position_codes; std::vector<uint32_t> m_position_codes;
std::vector<std::string> m_port_names; std::vector<std::string> m_port_names;
std::vector<std::array<double, 3>> m_positions; std::vector<osd::channel_position> m_positions;
osd::audio_rate_range m_rate; osd::audio_rate_range m_rate;
bool m_has_s16; bool m_has_s16;
@ -165,16 +165,16 @@ private:
// Try to more or less map to speaker.h positions // Try to more or less map to speaker.h positions
const sound_pipewire::position_info sound_pipewire::position_infos[] = { const sound_pipewire::position_info sound_pipewire::position_infos[] = {
{ SPA_AUDIO_CHANNEL_MONO, { 0.0, 0.0, 1.0 } }, { SPA_AUDIO_CHANNEL_MONO, osd::channel_position::FC },
{ SPA_AUDIO_CHANNEL_FL, { -0.2, 0.0, 1.0 } }, { SPA_AUDIO_CHANNEL_FL, osd::channel_position::FL },
{ SPA_AUDIO_CHANNEL_FR, { 0.2, 0.0, 1.0 } }, { SPA_AUDIO_CHANNEL_FR, osd::channel_position::FR },
{ SPA_AUDIO_CHANNEL_FC, { 0.0, 0.0, 1.0 } }, { SPA_AUDIO_CHANNEL_FC, osd::channel_position::FC },
{ SPA_AUDIO_CHANNEL_LFE, { 0.0, -0.5, 1.0 } }, { SPA_AUDIO_CHANNEL_LFE, osd::channel_position::LFE },
{ SPA_AUDIO_CHANNEL_RL, { -0.2, 0.0, -0.5 } }, { SPA_AUDIO_CHANNEL_RL, osd::channel_position::RL },
{ SPA_AUDIO_CHANNEL_RR, { 0.2, 0.0, -0.5 } }, { SPA_AUDIO_CHANNEL_RR, osd::channel_position::RR },
{ SPA_AUDIO_CHANNEL_RC, { 0.0, 0.0, -0.5 } }, { SPA_AUDIO_CHANNEL_RC, osd::channel_position::RC },
{ SPA_AUDIO_CHANNEL_AUX0, { 0.0, 0.0, 10.0 } }, { SPA_AUDIO_CHANNEL_AUX0, osd::channel_position::ONREQ },
{ SPA_AUDIO_CHANNEL_UNKNOWN, { 0.0, 0.0, 0.0 } } { SPA_AUDIO_CHANNEL_UNKNOWN, osd::channel_position::UNKNOWN }
}; };

View File

@ -45,7 +45,7 @@ public:
private: private:
struct position_info { struct position_info {
pa_channel_position_t m_position; pa_channel_position_t m_position;
std::array<double, 3> m_coords; osd::channel_position m_coords;
}; };
static const position_info position_infos[]; static const position_info position_infos[];
@ -61,7 +61,7 @@ private:
// Audio node info // Audio node info
std::vector<pa_channel_position_t> m_position_codes; std::vector<pa_channel_position_t> m_position_codes;
std::vector<std::string> m_position_names; std::vector<std::string> m_position_names;
std::vector<std::array<double, 3>> m_positions; std::vector<osd::channel_position> m_positions;
uint32_t m_sink_port_count, m_source_port_count; uint32_t m_sink_port_count, m_source_port_count;
osd::audio_rate_range m_rate; osd::audio_rate_range m_rate;
@ -122,15 +122,15 @@ private:
// Try to more or less map to speaker.h positions // Try to more or less map to speaker.h positions
const sound_pulse::position_info sound_pulse::position_infos[] = { const sound_pulse::position_info sound_pulse::position_infos[] = {
{ PA_CHANNEL_POSITION_MONO, { 0.0, 0.0, 1.0 } }, { PA_CHANNEL_POSITION_MONO, osd::channel_position::FC },
{ PA_CHANNEL_POSITION_FRONT_LEFT, { -0.2, 0.0, 1.0 } }, { PA_CHANNEL_POSITION_FRONT_LEFT, osd::channel_position::FL },
{ PA_CHANNEL_POSITION_FRONT_RIGHT, { 0.2, 0.0, 1.0 } }, { PA_CHANNEL_POSITION_FRONT_RIGHT, osd::channel_position::FR },
{ PA_CHANNEL_POSITION_FRONT_CENTER, { 0.0, 0.0, 1.0 } }, { PA_CHANNEL_POSITION_FRONT_CENTER, osd::channel_position::FC },
{ PA_CHANNEL_POSITION_LFE, { 0.0, -0.5, 1.0 } }, { PA_CHANNEL_POSITION_LFE, osd::channel_position::LFE },
{ PA_CHANNEL_POSITION_REAR_LEFT, { -0.2, 0.0, -0.5 } }, { PA_CHANNEL_POSITION_REAR_LEFT, osd::channel_position::RL },
{ PA_CHANNEL_POSITION_REAR_RIGHT, { 0.2, 0.0, -0.5 } }, { PA_CHANNEL_POSITION_REAR_RIGHT, osd::channel_position::RR },
{ PA_CHANNEL_POSITION_REAR_CENTER, { 0.0, 0.0, -0.5 } }, { PA_CHANNEL_POSITION_REAR_CENTER, osd::channel_position::RC },
{ PA_CHANNEL_POSITION_MAX, { 0.0, 0.0, 10.0 } } { PA_CHANNEL_POSITION_MAX, osd::channel_position::ONREQ },
}; };

View File

@ -148,17 +148,17 @@ osd::audio_info sound_sdl::get_information()
enum { FL, FR, FC, LFE, BL, BR, BC, SL, SR, AUX }; enum { FL, FR, FC, LFE, BL, BR, BC, SL, SR, AUX };
static const char *const posname[10] = { "FL", "FR", "FC", "LFE", "BL", "BR", "BC", "SL", "SR", "AUX" }; static const char *const posname[10] = { "FL", "FR", "FC", "LFE", "BL", "BR", "BC", "SL", "SR", "AUX" };
static std::array<double, 3> pos3d[10] = { static const osd::channel_position pos3d[10] = {
{ -0.2, 0.0, 1.0 }, osd::channel_position::FL,
{ 0.2, 0.0, 1.0 }, osd::channel_position::FR,
{ 0.0, 0.0, 1.0 }, osd::channel_position::FC,
{ 0.0, -0.5, 1.0 }, osd::channel_position::LFE,
{ -0.2, 0.0, -0.5 }, osd::channel_position::RL,
{ 0.2, 0.0, -0.5 }, osd::channel_position::RR,
{ 0.0, 0.0, -0.5 }, osd::channel_position::RC,
{ -0.2, 0.0, 0.0 }, osd::channel_position(-0.2, 0.0, 0.0),
{ 0.2, 0.0, 0.0 }, osd::channel_position( 0.2, 0.0, 0.0),
{ 0.0, 0.0, 10.0 }, osd::channel_position::ONREQ
}; };
static const uint32_t positions[8][9] = { static const uint32_t positions[8][9] = {

View File

@ -30,8 +30,8 @@ osd::audio_info sound_module::get_information()
result.m_nodes[0].m_sources = 0; result.m_nodes[0].m_sources = 0;
result.m_nodes[0].m_port_names.emplace_back("L"); result.m_nodes[0].m_port_names.emplace_back("L");
result.m_nodes[0].m_port_names.emplace_back("R"); result.m_nodes[0].m_port_names.emplace_back("R");
result.m_nodes[0].m_port_positions.emplace_back(std::array<double, 3>({ -0.2, 0.0, 1.0 })); result.m_nodes[0].m_port_positions.emplace_back(osd::channel_position::FL);
result.m_nodes[0].m_port_positions.emplace_back(std::array<double, 3>({ 0.2, 0.0, 1.0 })); result.m_nodes[0].m_port_positions.emplace_back(osd::channel_position::FR);
result.m_streams.resize(1); result.m_streams.resize(1);
result.m_streams[0].m_id = 1; result.m_streams[0].m_id = 1;
result.m_streams[0].m_node = 1; result.m_streams[0].m_node = 1;
@ -40,13 +40,18 @@ osd::audio_info sound_module::get_information()
sound_module::abuffer::abuffer(uint32_t channels) noexcept : m_channels(channels), m_used_buffers(0), m_last_sample(channels, 0) sound_module::abuffer::abuffer(uint32_t channels) noexcept : m_channels(channels), m_used_buffers(0), m_last_sample(channels, 0)
{ {
m_delta = 0;
m_delta2 = 0;
} }
void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept
{ {
m_delta -= samples;
m_delta2 -= samples;
uint32_t pos = 0; uint32_t pos = 0;
while(pos != samples) { while(pos != samples) {
if(!m_used_buffers) { if(!m_used_buffers) {
m_delta2 += samples - pos;
while(pos != samples) { while(pos != samples) {
std::copy_n(m_last_sample.data(), m_channels, data); std::copy_n(m_last_sample.data(), m_channels, data);
data += m_channels; data += m_channels;
@ -74,10 +79,13 @@ void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept
pos += avail; pos += avail;
data += avail * m_channels; data += avail * m_channels;
} }
// printf("# %d %d\n", m_delta, m_delta2);
} }
void sound_module::abuffer::push(const int16_t *data, uint32_t samples) void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
{ {
m_delta += samples;
m_delta2 += samples;
auto &buf = push_buffer(); auto &buf = push_buffer();
buf.m_cpos = 0; buf.m_cpos = 0;
buf.m_data.resize(samples * m_channels); buf.m_data.resize(samples * m_channels);
@ -85,6 +93,8 @@ void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
std::copy_n(data + ((samples - 1) * m_channels), m_channels, m_last_sample.data()); std::copy_n(data + ((samples - 1) * m_channels), m_channels, m_last_sample.data());
if(m_used_buffers > 10) { if(m_used_buffers > 10) {
for(uint32_t i=0; i != m_used_buffers-10; i++)
m_delta2 -= (m_buffers[i].m_data.size()/m_channels - m_buffers[i].m_cpos);
// If there are way too many buffers, drop some so only 10 are left (roughly 0.2s) // If there are way too many buffers, drop some so only 10 are left (roughly 0.2s)
for(unsigned i = 0; 10 > i; ++i) { for(unsigned i = 0; 10 > i; ++i) {
using std::swap; using std::swap;
@ -95,8 +105,10 @@ void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
// If there are too many buffers, remove five samples per buffer // If there are too many buffers, remove five samples per buffer
// to slowly resync to reduce latency (4 seconds to // to slowly resync to reduce latency (4 seconds to
// compensate one buffer, roughly) // compensate one buffer, roughly)
m_delta2 -= std::max<uint32_t>(samples / 200, 1);
buf.m_cpos = std::max<uint32_t>(samples / 200, 1); buf.m_cpos = std::max<uint32_t>(samples / 200, 1);
} }
// printf("# %d %d\n", m_delta, m_delta2);
} }
uint32_t sound_module::abuffer::available() const noexcept uint32_t sound_module::abuffer::available() const noexcept

View File

@ -63,6 +63,7 @@ protected:
void pop_buffer() noexcept; void pop_buffer() noexcept;
buffer &push_buffer(); buffer &push_buffer();
int32_t m_delta, m_delta2;
uint32_t m_channels; uint32_t m_channels;
uint32_t m_used_buffers; uint32_t m_used_buffers;
std::vector<int16_t> m_last_sample; std::vector<int16_t> m_last_sample;