mirror of
https://github.com/holub/mame
synced 2025-06-24 05:17:04 +03:00
sound:
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:
parent
292b999b03
commit
f0e6df8048
@ -99,6 +99,8 @@ files {
|
||||
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.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.h",
|
||||
MAME_DIR .. "src/frontend/mame/ui/barcode.cpp",
|
||||
|
@ -52,6 +52,7 @@ function osdmodulesbuild()
|
||||
files {
|
||||
MAME_DIR .. "src/osd/watchdog.cpp",
|
||||
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/inputcode.h",
|
||||
MAME_DIR .. "src/osd/interface/inputdev.h",
|
||||
|
@ -739,7 +739,7 @@ void vgmviz_device::draw_waveform(bitmap_rgb32 &bitmap)
|
||||
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 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 endy_l = CHANNEL_CENTER;
|
||||
int y = endy_l - sample_l;
|
||||
@ -750,7 +750,7 @@ void vgmviz_device::draw_waveform(bitmap_rgb32 &bitmap)
|
||||
} 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 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 endy_r = CHANNEL_HEIGHT + 1 + CHANNEL_CENTER;
|
||||
y = endy_r - sample_r;
|
||||
|
@ -15,13 +15,13 @@ const char *const audio_effect::effect_names[COUNT] = {
|
||||
"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) {
|
||||
case FILTER: return new audio_effect_filter (sample_rate, def);
|
||||
case COMPRESSOR: return new audio_effect_compressor(sample_rate, def);
|
||||
case REVERB: return new audio_effect_reverb (sample_rate, def);
|
||||
case EQ: return new audio_effect_eq (sample_rate, def);
|
||||
case FILTER: return new audio_effect_filter (speaker, sample_rate, def);
|
||||
case COMPRESSOR: return new audio_effect_compressor(speaker, sample_rate, def);
|
||||
case REVERB: return new audio_effect_reverb (speaker, sample_rate, def);
|
||||
case EQ: return new audio_effect_eq (speaker, sample_rate, def);
|
||||
}
|
||||
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();
|
||||
dest.prepare_space(samples);
|
||||
u32 channels = src.channels();
|
||||
for(u32 channel = 0; channel != channels; channel++) {
|
||||
for(u32 channel = 0; channel != m_channels; channel++) {
|
||||
const sample_t *srcd = src.ptrs(channel, 0);
|
||||
sample_t *destd = dest.ptrw(channel, 0);
|
||||
std::copy(srcd, srcd + samples, destd);
|
||||
|
@ -6,6 +6,8 @@
|
||||
#ifndef MAME_EMU_AUDIO_EFFECTS_AEFFECT_H
|
||||
#define MAME_EMU_AUDIO_EFFECTS_AEFFECT_H
|
||||
|
||||
#include "speaker.h"
|
||||
|
||||
class audio_effect
|
||||
{
|
||||
public:
|
||||
@ -21,9 +23,9 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
audio_effect *m_default;
|
||||
u32 m_sample_rate;
|
||||
speaker_device *m_speaker;
|
||||
u32 m_channels, m_sample_rate;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -7,8 +7,15 @@
|
||||
#include "compressor.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_attack();
|
||||
reset_release();
|
||||
@ -362,23 +369,14 @@ void audio_effect_compressor::apply(const emu::detail::output_buffer_flat<sample
|
||||
}
|
||||
|
||||
u32 samples = src.available_samples();
|
||||
u32 channels = src.channels();
|
||||
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 release_coefficient = exp(-1/(m_sample_rate * m_release / 1000));
|
||||
double m_inertia_decay_coefficient = 0.99 + m_inertia_decay * 0.01;
|
||||
|
||||
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;
|
||||
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];
|
||||
for(u32 channel = 1; channel < channels; channel++)
|
||||
for(u32 channel = 1; channel != m_channels; channel++)
|
||||
if(m_gain_reduction[channel] > max_gain)
|
||||
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);
|
||||
double output_sample = db_to_value(m_input_samples[channel] - m_gain_reduction[channel]);
|
||||
if(*src.ptrs(channel, sample) < 0)
|
||||
|
@ -11,7 +11,7 @@
|
||||
class audio_effect_compressor : public audio_effect
|
||||
{
|
||||
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 int type() const override { return COMPRESSOR; }
|
||||
|
@ -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 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_*
|
||||
// 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();
|
||||
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);
|
||||
sample_t *destd = dest.ptrw(channel, 0);
|
||||
for(u32 sample = 0; sample != samples; sample++) {
|
||||
|
@ -13,7 +13,7 @@ class audio_effect_eq : public audio_effect
|
||||
public:
|
||||
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 int type() const override { return EQ; }
|
||||
|
@ -13,8 +13,11 @@
|
||||
// [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_*
|
||||
// recomputes filters
|
||||
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();
|
||||
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);
|
||||
sample_t *destd = dest.ptrw(channel, 0);
|
||||
for(u32 sample = 0; sample != samples; sample++) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
class audio_effect_filter : public audio_effect
|
||||
{
|
||||
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 int type() const override { return FILTER; }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,10 +8,12 @@
|
||||
|
||||
#include "aeffect.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
class audio_effect_reverb : public audio_effect
|
||||
{
|
||||
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 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_save(util::xml::data_node *ef_node) const 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
|
||||
|
@ -308,7 +308,8 @@ sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 sample
|
||||
m_sync_timer(nullptr),
|
||||
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
|
||||
m_name = m_device.name();
|
||||
@ -854,7 +855,7 @@ void sound_manager::after_devices_init()
|
||||
|
||||
// Create the default effect chain
|
||||
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
|
||||
m_outputs_count = 0;
|
||||
@ -862,7 +863,7 @@ void sound_manager::after_devices_init()
|
||||
dev.set_id(m_speakers.size());
|
||||
m_speakers.emplace_back(speaker_info(dev, machine().sample_rate(), m_outputs_count));
|
||||
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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
if(pos.is_onreq())
|
||||
return result;
|
||||
|
||||
double best_dist = -1;
|
||||
for(u32 port = 0; port != node->m_port_positions.size(); port++)
|
||||
if(sound_io_device::mapping_allowed(node->m_port_positions[port])) {
|
||||
double dx = position[0] - node->m_port_positions[port][0];
|
||||
double dy = position[1] - node->m_port_positions[port][1];
|
||||
double dz = position[2] - node->m_port_positions[port][2];
|
||||
if(!node->m_port_positions[port].is_onreq() && !node->m_port_positions[port].is_lfe()) {
|
||||
double dx = pos.m_x - node->m_port_positions[port].m_z;
|
||||
double dy = pos.m_y - node->m_port_positions[port].m_y;
|
||||
double dz = pos.m_z - node->m_port_positions[port].m_z;
|
||||
double dist = dx*dx + dy*dy + dz*dz;
|
||||
if(best_dist == -1 || dist < best_dist) {
|
||||
best_dist = dist;
|
||||
@ -2496,12 +2504,10 @@ void sound_manager::mapping_update()
|
||||
if(port_count < node.m_sources)
|
||||
port_count = node.m_sources;
|
||||
for(uint32_t port = 0; port != port_count; port++)
|
||||
LOG_OUTPUT_FUNC(" %s %s [%g %g %g]\n",
|
||||
(port < node.m_sinks) ? ((port < node.m_sources) ? "<>" : ">") : "<",
|
||||
node.m_port_names[port],
|
||||
node.m_port_positions[port][0],
|
||||
node.m_port_positions[port][1],
|
||||
node.m_port_positions[port][2]);
|
||||
LOG_OUTPUT_FUNC(" %s %s [%s]\n",
|
||||
port < node.m_sinks ? port < node.m_sources ? "<>" : ">" : "<",
|
||||
node.m_port_names[port].c_str(),
|
||||
node.m_port_positions[port].name());
|
||||
}
|
||||
LOG_OUTPUT_FUNC("- streams:\n");
|
||||
for(const auto &stream : m_osd_info.m_streams) {
|
||||
|
@ -50,8 +50,8 @@
|
||||
By default, the inputs will have been resampled to match the output
|
||||
sample rate, unless otherwise specified.
|
||||
|
||||
SOUND_DISABLE_THREADING if to be defined when your environment does
|
||||
not support threads (e.g. emscripten). The effects suddendly become
|
||||
SOUND_DISABLE_THREADING is to be defined when your environment does
|
||||
not support threads (e.g. emscripten). The effects suddenly become
|
||||
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_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)>;
|
||||
class audio_effect;
|
||||
@ -599,7 +582,7 @@ private:
|
||||
void update(s32);
|
||||
|
||||
// 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 streams_update();
|
||||
template<bool is_output, typename S> void apply_osd_changes(std::vector<S> &streams);
|
||||
|
@ -18,37 +18,21 @@
|
||||
DEFINE_DEVICE_TYPE(SPEAKER, speaker_device, "speaker", "Speaker")
|
||||
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)
|
||||
{
|
||||
if(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][1] = y;
|
||||
m_positions[channel][2] = z;
|
||||
m_positions[channel].m_x = x;
|
||||
m_positions[channel].m_y = y;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -41,30 +41,32 @@ DECLARE_DEVICE_TYPE(MICROPHONE, microphone_device)
|
||||
class sound_io_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~sound_io_device();
|
||||
|
||||
// configuration helpers
|
||||
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 &front_left(u32 channel = 0) { return set_position(channel, -0.2, 0.0, 1.0); }
|
||||
sound_io_device &front_floor(u32 channel = 0) { return set_position(channel, 0.0, -0.5, 1.0); }
|
||||
sound_io_device &front_right(u32 channel = 0) { return set_position(channel, 0.2, 0.0, 1.0); }
|
||||
sound_io_device &rear_center(u32 channel = 0) { return set_position(channel, 0.0, 0.0, -0.5); }
|
||||
sound_io_device &rear_left(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, 0.2, 0.0, -0.5); }
|
||||
sound_io_device &headrest_center(u32 channel = 0) { return set_position(channel, 0.0, 0.0, -0.1); }
|
||||
sound_io_device &headrest_left(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, 0.1, 0.0, -0.1); }
|
||||
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, 0.0, -0.2, 0.1); }
|
||||
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, 0.0, 0.0, 10.0); }
|
||||
sound_io_device &set_position(u32 channel, const osd::channel_position &pos);
|
||||
sound_io_device &front_center(u32 channel = 0) { return set_position(channel, osd::channel_position::FC); }
|
||||
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, osd::channel_position::FR); }
|
||||
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, osd::channel_position::RL); }
|
||||
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, osd::channel_position::HC); }
|
||||
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, osd::channel_position::RC); }
|
||||
sound_io_device &backrest(u32 channel = 0) { return set_position(channel, osd::channel_position::BACKREST); }
|
||||
sound_io_device &unknown(u32 channel = 0) { return set_position(channel, osd::channel_position::UNKNOWN); }
|
||||
sound_io_device &map_on_request_only(u32 channel = 0) { return set_position(channel, osd::channel_position::ONREQ); }
|
||||
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 &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); }
|
||||
|
||||
int channels() const { return m_positions.size(); }
|
||||
std::array<double, 3> get_position(u32 channel) const { return m_positions[channel]; }
|
||||
std::string get_position_name(u32 channel) const;
|
||||
const osd::channel_position &get_position(u32 channel) const { return m_positions[channel]; }
|
||||
|
||||
virtual bool is_output() const = 0;
|
||||
void set_id(int id) { m_id = id; }
|
||||
@ -72,20 +74,9 @@ public:
|
||||
|
||||
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:
|
||||
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
|
||||
std::vector<std::array<double, 3>> m_positions;
|
||||
std::vector<osd::channel_position> m_positions;
|
||||
sound_stream *m_stream;
|
||||
int m_id;
|
||||
|
||||
|
@ -1696,9 +1696,9 @@ void lua_engine::initialize()
|
||||
{
|
||||
auto pos = iodev->get_position(channel);
|
||||
auto table = sol().create_table();
|
||||
table[1] = pos[0];
|
||||
table[2] = pos[1];
|
||||
table[3] = pos[2];
|
||||
table[1] = pos.m_x;
|
||||
table[2] = pos.m_y;
|
||||
table[3] = pos.m_z;
|
||||
pos_table[channel+1] = table;
|
||||
}
|
||||
return pos_table;
|
||||
@ -1710,7 +1710,7 @@ void lua_engine::initialize()
|
||||
auto *iodev = dynamic_cast<sound_io_device *>(&dev.device());
|
||||
if (iodev)
|
||||
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;
|
||||
});
|
||||
|
||||
|
655
src/frontend/mame/ui/audio_effect_reverb.cpp
Normal file
655
src/frontend/mame/ui/audio_effect_reverb.cpp
Normal 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;
|
||||
}
|
||||
}
|
88
src/frontend/mame/ui/audio_effect_reverb.h
Normal file
88
src/frontend/mame/ui/audio_effect_reverb.h
Normal 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
|
@ -15,6 +15,7 @@
|
||||
#include "audio_effect_compressor.h"
|
||||
#include "audio_effect_eq.h"
|
||||
#include "audio_effect_filter.h"
|
||||
#include "audio_effect_reverb.h"
|
||||
|
||||
#include "ui/ui.h"
|
||||
|
||||
@ -106,6 +107,10 @@ bool menu_audio_effects::handle(event const *ev)
|
||||
case audio_effect::FILTER:
|
||||
menu::stack_push<menu_audio_effect_filter>(ui(), container(), chain, entry, eff);
|
||||
break;
|
||||
|
||||
case audio_effect::REVERB:
|
||||
menu::stack_push<menu_audio_effect_reverb>(ui(), container(), chain, entry, eff);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ void menu_audio_mixer::populate()
|
||||
}
|
||||
for(const auto &cmap : omap.m_channel_mappings) {
|
||||
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)
|
||||
guest_channel = u8"\u25c4" + guest_channel + u8"\u25ba";
|
||||
|
||||
|
@ -903,7 +903,7 @@ void atarigt_state::atarigt_stereo(machine_config &config)
|
||||
// based on dedicated cabinet configuration;
|
||||
// 'universal' kit supports mono and stereo, with/without subwoofer.
|
||||
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.
|
||||
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)
|
||||
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->add_route(0, "speaker", 1.0, 1); // Foward Right
|
||||
|
@ -761,7 +761,7 @@ void metalmx_state::metalmx(machine_config &config)
|
||||
// TODO: copied from atarigt.cpp; Same configurations as T-Mek?
|
||||
// 5 Channel output (4 Channel input connected to Quad Amp PCB)
|
||||
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);
|
||||
m_cage->set_speedup(0); // TODO: speedup address
|
||||
|
@ -2171,7 +2171,7 @@ void seattle_state::sfrush(machine_config &config)
|
||||
|
||||
// 5 Channel output (4 Channel input connected to Quad Amp PCB)
|
||||
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);
|
||||
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)
|
||||
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);
|
||||
m_cage->set_speedup(0x5329);
|
||||
|
@ -3846,7 +3846,7 @@ void namcos22s_state::airco22b(machine_config &config)
|
||||
{
|
||||
namcos22s(config);
|
||||
|
||||
SPEAKER(config, "bodysonic").backrest();
|
||||
SPEAKER(config, "bodysonic").lfe();
|
||||
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);
|
||||
|
||||
SPEAKER(config, "vibration").seat();
|
||||
SPEAKER(config, "vibration").lfe();
|
||||
SPEAKER(config, "seat").headrest_center();
|
||||
|
||||
m_c352->add_route(2, "vibration", 0.5); // to "bass shaker"
|
||||
|
@ -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_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
|
||||
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
|
||||
m_ps88->add_route(0, "cabinet", 1.0);
|
||||
m_ps88->add_route(1, "backbox", 1.0);
|
||||
|
@ -974,7 +974,7 @@ void ninjaw_state::ninjaw(machine_config &config)
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "speaker", 2).front();
|
||||
SPEAKER(config, "subwoofer").seat();
|
||||
SPEAKER(config, "subwoofer").lfe();
|
||||
|
||||
ym2610_device &ymsnd(YM2610(config, "ymsnd", 16000000/2));
|
||||
ymsnd.irq_handler().set_inputline("audiocpu", 0);
|
||||
@ -1079,7 +1079,7 @@ void ninjaw_state::darius2(machine_config &config)
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "speaker", 2).front();
|
||||
SPEAKER(config, "subwoofer").seat();
|
||||
SPEAKER(config, "subwoofer").lfe();
|
||||
|
||||
ym2610_device &ymsnd(YM2610(config, "ymsnd", 16000000/2));
|
||||
ymsnd.irq_handler().set_inputline("audiocpu", 0);
|
||||
|
@ -3221,7 +3221,7 @@ void contcirc_state::contcirc(machine_config &config) //OSC: 26.686, 24.000, 16.
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "front").front_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
|
||||
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 */
|
||||
SPEAKER(config, "front").front_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
|
||||
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 */
|
||||
SPEAKER(config, "front").front_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
|
||||
ymsnd.irq_handler().set_inputline(m_audiocpu, 0);
|
||||
|
@ -1155,7 +1155,7 @@ void dendego_state::dendego(machine_config &config)
|
||||
m_screen->set_screen_update(FUNC(dendego_state::screen_update_dendego));
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "vibration").seat();
|
||||
SPEAKER(config, "vibration").lfe();
|
||||
|
||||
/* clock frequency & pin 7 not verified */
|
||||
OKIM6295(config, "oki", 1056000, okim6295_device::PIN7_HIGH).add_route(ALL_OUTPUTS, "vibration", 0.20);
|
||||
|
@ -630,7 +630,7 @@ void warriorb_state::darius2d(machine_config &config)
|
||||
|
||||
// sound hardware
|
||||
SPEAKER(config, "speaker", 2).front();
|
||||
SPEAKER(config, "subwoofer").seat();
|
||||
SPEAKER(config, "subwoofer").lfe();
|
||||
|
||||
ym2610_device &ymsnd(YM2610(config, "ymsnd", 16_MHz_XTAL / 2));
|
||||
ymsnd.irq_handler().set_inputline("audiocpu", 0);
|
||||
|
49
src/osd/interface/audio.cpp
Normal file
49
src/osd/interface/audio.cpp
Normal 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);
|
||||
}
|
||||
|
@ -16,6 +16,57 @@
|
||||
|
||||
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 {
|
||||
uint32_t m_default_rate;
|
||||
uint32_t m_min_rate;
|
||||
@ -41,7 +92,7 @@ struct audio_info {
|
||||
uint32_t m_id;
|
||||
audio_rate_range m_rate;
|
||||
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_sources;
|
||||
|
||||
|
@ -102,62 +102,62 @@ static const char *sMacChannelLabels[sMacChannelCount] =
|
||||
// "Surround" channels are at X = -0.4 (left) and 0.4 (right).
|
||||
static const std::array<double,3> sChannelPositions[sMacChannelCount] =
|
||||
{
|
||||
{ 0.0, 0.0, 0.0 }, // unused
|
||||
{ -0.2, 0.0, 1.0 }, // Front Left
|
||||
{ 0.2, 0.0, 1.0 }, // Front Right
|
||||
{ 0.0, 0.0, 1.0 }, // Front Center
|
||||
{ 0.0, -0.5, 0.0 }, // Low Frequency Effects
|
||||
{ -0.2, 0.0, -0.5 }, // Rear Left
|
||||
{ 0.2, 0.0, -0.5 }, // Rear Right
|
||||
{ -0.1, 0.0, 1.0 }, // Front Left of Center
|
||||
{ 0.1, 0.0, 1.0 }, // Front Right of Center
|
||||
{ 0.0, 0.0, -1.0 }, // Rear Center
|
||||
{ -0.2, 0.0, 0.5 }, // Side Left
|
||||
{ 0.2, 0.0, 0.5 }, // Side Right
|
||||
{ 0.0, 0.5, -0.1 }, // Top Center
|
||||
{ -0.2, 0.5, 1.0 }, // Top Front Left
|
||||
{ 0.0, 0.5, 1.0 }, // Top Front Center
|
||||
{ 0.2, 0.5, 1.0 }, // Top Front Right
|
||||
{ -0.2, 0.5, -0.5 }, // Top Rear Left
|
||||
{ 0.2, 0.5, -0.5 }, // Top Rear Center
|
||||
{ 0.2, 0.5, -0.5 }, // Top Rear Right
|
||||
{ 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 }, { 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.4, 0.0, -0.5 }, // Rear Surround Left
|
||||
{ 0.4, 0.0, -0.5 }, // Rear Surround Right
|
||||
{ -0.4, 0.0, 1.0 }, // Left Wide
|
||||
{ 0.4, 0.0, 1.0 }, // Right Wide
|
||||
{ 0.0, -0.5, 0.0 }, // Low Frequency Effects 2
|
||||
{ -0.1, 0.0, -0.1 }, // Left Total
|
||||
{ 0.1, 0.0, -0.1 }, // Right Total
|
||||
{ 0.0, 0.0, 1.0 }, // Hearing Impaired
|
||||
{ 0.0, 0.0, 1.0 }, // Narration
|
||||
{ 0.0, 0.0, 1.0 }, // Mono
|
||||
{ 0.0, 0.0, 1.0 }, // Dialog Centric Mix
|
||||
{ 0.0, 0.0, -0.1 }, // Center Surround Direct
|
||||
{ 0.0, 0.0, 0.0 }, // Haptic
|
||||
{ 0.0, 0.0, 0.0 }, // unused
|
||||
{ 0.0, 0.0, 0.0 }, // unused
|
||||
{ 0.0, 0.0, 0.0 }, // unused
|
||||
{ -0.2, 0.5, 0.0 }, // Left Top Middle
|
||||
{ 0.0, 0.0, 0.0 }, // unused
|
||||
{ 0.2, 0.5, 0.0 }, // Right Top Middle
|
||||
{ -0.2, 0.5, -0.5 }, // Left Top Rear
|
||||
{ 0.0, 0.5, -0.5 }, // Center Top Rear
|
||||
{ 0.2, 0.5, -0.5 }, // Right Top Rear
|
||||
{ -0.4, 0.0, -0.1 }, // Left Side Surround
|
||||
{ 0.4, 0.0, -0.1 }, // Right Side Surround
|
||||
{ -0.2, -0.5, 0.0 }, // Left Bottom
|
||||
{ 0.2, -0.5, 0.0 }, // Right Bottom
|
||||
{ 0.0, -0.5, 0.0 }, // Center Bottom
|
||||
{ -0.4, 0.5, -0.1 }, // Left Top Surround
|
||||
{ 0.4, 0.5, -0.1 }, // Right Top Surround
|
||||
{ 0.0, 0.0, 0.0 }, // Low Frequency Effects 3
|
||||
{ -0.4, 0.0, -0.5 }, // Left Rear Surround
|
||||
{ 0.4, 0.0, -0.5 }, // Right Rear Surround
|
||||
{ -0.1, 0.0, 1.0 }, // Left Edge of Screen
|
||||
{ 0.1, 0.0, 1.0 } // Right Edge of Screen
|
||||
osd::channel_position::UNKNOWN, // unused
|
||||
osd::channel_position::FL, // Front Left
|
||||
osd::channel_position::FR, // Front Right
|
||||
osd::channel_position::FC, // Front Center
|
||||
osd::channel_position::LFE, // Low Frequency Effects
|
||||
osd::channel_position::RL, // Rear Left
|
||||
osd::channel_position::RR, // Rear Right
|
||||
osd::channel_position( -0.1, 0.0, 1.0 ), // Front Left of Center
|
||||
osd::channel_position( 0.1, 0.0, 1.0 ), // Front Right of Center
|
||||
osd::channel_position::RC, // Rear Center
|
||||
osd::channel_position( -0.2, 0.0, 0.5 ), // Side Left
|
||||
osd::channel_position( 0.2, 0.0, 0.5 ), // Side Right
|
||||
osd::channel_position( 0.0, 0.5, -0.1 ), // Top Center
|
||||
osd::channel_position( -0.2, 0.5, 1.0 ), // Top Front Left
|
||||
osd::channel_position( 0.0, 0.5, 1.0 ), // Top Front Center
|
||||
osd::channel_position( 0.2, 0.5, 1.0 ), // Top Front Right
|
||||
osd::channel_position( -0.2, 0.5, -0.5 ), // Top Rear Left
|
||||
osd::channel_position( 0.2, 0.5, -0.5 ), // Top Rear Center
|
||||
osd::channel_position( 0.2, 0.5, -0.5 ), // Top Rear Right
|
||||
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, osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN,
|
||||
osd::channel_position::UNKNOWN, osd::channel_position::UNKNOWN,
|
||||
osd::channel_position( -0.4, 0.0, -0.5 ), // Rear Surround Left
|
||||
osd::channel_position( 0.4, 0.0, -0.5 ), // Rear Surround Right
|
||||
osd::channel_position( -0.4, 0.0, 1.0 ), // Left Wide
|
||||
osd::channel_position( 0.4, 0.0, 1.0 ), // Right Wide
|
||||
osd::channel_position::LFE, // Low Frequency Effects 2
|
||||
osd::channel_position::HL, // Left Total
|
||||
osd::channel_position::HR, // Right Total
|
||||
osd::channel_position::FC, // Hearing Impaired
|
||||
osd::channel_position::FC, // Narration
|
||||
osd::channel_position::FC, // Mono
|
||||
osd::channel_position::FC, // Dialog Centric Mix
|
||||
osd::channel_position::HC, // Center Surround Direct
|
||||
osd::channel_position::UNKNOWN, // Haptic
|
||||
osd::channel_position::UNKNOWN, // unused
|
||||
osd::channel_position::UNKNOWN, // unused
|
||||
osd::channel_position::UNKNOWN, // unused
|
||||
osd::channel_position( -0.2, 0.5, 0.0 ), // Left Top Middle
|
||||
osd::channel_position::UNKNOWN, // unused
|
||||
osd::channel_position( 0.2, 0.5, 0.0 ), // Right Top Middle
|
||||
osd::channel_position( -0.2, 0.5, -0.5 ), // Left Top Rear
|
||||
osd::channel_position( 0.0, 0.5, -0.5 ), // Center Top Rear
|
||||
osd::channel_position( 0.2, 0.5, -0.5 ), // Right Top Rear
|
||||
osd::channel_position( -0.4, 0.0, -0.1 ), // Left Side Surround
|
||||
osd::channel_position( 0.4, 0.0, -0.1 ), // Right Side Surround
|
||||
osd::channel_position( -0.2, -0.5, 0.0 ), // Left Bottom
|
||||
osd::channel_position( 0.2, -0.5, 0.0 ), // Right Bottom
|
||||
osd::channel_position( 0.0, -0.5, 0.0 ), // Center Bottom
|
||||
osd::channel_position( -0.4, 0.5, -0.1 ), // Left Top Surround
|
||||
osd::channel_position( 0.4, 0.5, -0.1 ), // Right Top Surround
|
||||
osd::channel_position::UNKNOWN, // Low Frequency Effects 3
|
||||
osd::channel_position( -0.4, 0.0, -0.5 ), // Left Rear Surround
|
||||
osd::channel_position( 0.4, 0.0, -0.5 ), // Right Rear Surround
|
||||
osd::channel_position( -0.1, 0.0, 1.0 ), // Left Edge of Screen
|
||||
osd::channel_position( 0.1, 0.0, 1.0 ) // Right Edge of Screen
|
||||
};
|
||||
|
||||
struct coreaudio_device
|
||||
@ -1064,7 +1064,7 @@ void sound_coreaudio::build_device_list()
|
||||
{
|
||||
std::string chLabel = "Channel " + std::to_string(desc + 1);
|
||||
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
|
||||
{
|
||||
|
@ -48,25 +48,25 @@ char const *const f_speaker_names[] ={
|
||||
"TBC", // SPEAKER_TOP_BACK_CENTER
|
||||
"TBR" }; // SPEAKER_TOP_BACK_RIGHT
|
||||
|
||||
std::array<double, 3> const f_speaker_positions[] = {
|
||||
{ -0.2, 0.0, 1.0 }, // SPEAKER_FRONT_LEFT
|
||||
{ 0.2, 0.0, 1.0 }, // SPEAKER_FRONT_RIGHT
|
||||
{ 0.0, 0.0, 1.0 }, // SPEAKER_FRONT_CENTER
|
||||
{ 0.0, -0.5, 1.0 }, // SPEAKER_LOW_FREQUENCY
|
||||
{ -0.2, 0.0, -0.5 }, // SPEAKER_BACK_LEFT
|
||||
{ 0.2, 0.0, -0.5 }, // SPEAKER_BACK_RIGHT
|
||||
{ -0.1, 0.0, 1.0 }, // SPEAKER_FRONT_LEFT_OF_CENTER
|
||||
{ 0.1, 0.0, 1.0 }, // SPEAKER_FRONT_RIGHT_OF_CENTER
|
||||
{ 0.0, 0.0, -0.5 }, // SPEAKER_BACK_CENTER
|
||||
{ -0.2, 0.0, 0.0 }, // SPEAKER_SIDE_LEFT
|
||||
{ 0.2, 0.0, 0.0 }, // SPEAKER_SIDE_RIGHT
|
||||
{ 0.0, 0.5, 0.0 }, // SPEAKER_TOP_CENTER
|
||||
{ -0.2, 0.5, 1.0 }, // SPEAKER_TOP_FRONT_LEFT
|
||||
{ 0.0, 0.5, 1.0 }, // SPEAKER_TOP_FRONT_CENTER
|
||||
{ 0.2, 0.5, 1.0 }, // SPEAKER_TOP_FRONT_RIGHT
|
||||
{ -0.2, 0.5, -0.5 }, // SPEAKER_TOP_BACK_LEFT
|
||||
{ 0.0, 0.5, -0.5 }, // SPEAKER_TOP_BACK_CENTER
|
||||
{ 0.2, 0.5, -0.5 } }; // SPEAKER_TOP_BACK_RIGHT
|
||||
osd::channel_position const f_speaker_positions[] = {
|
||||
osd::channel_position::FL, // SPEAKER_FRONT_LEFT
|
||||
osd::channel_position::FR, // SPEAKER_FRONT_RIGHT
|
||||
osd::channel_position::FC, // SPEAKER_FRONT_CENTER
|
||||
osd::channel_position::LFE, // SPEAKER_LOW_FREQUENCY
|
||||
osd::channel_position::RL, // SPEAKER_BACK_LEFT
|
||||
osd::channel_position::RR, // SPEAKER_BACK_RIGHT
|
||||
osd::channel_position( -0.1, 0.0, 1.0 ), // SPEAKER_FRONT_LEFT_OF_CENTER
|
||||
osd::channel_position( 0.1, 0.0, 1.0 ), // SPEAKER_FRONT_RIGHT_OF_CENTER
|
||||
osd::channel_position::RC, // SPEAKER_BACK_CENTER
|
||||
osd::channel_position( -0.2, 0.0, 0.0 ), // SPEAKER_SIDE_LEFT
|
||||
osd::channel_position( 0.2, 0.0, 0.0 ), // SPEAKER_SIDE_RIGHT
|
||||
osd::channel_position( 0.0, 0.5, 0.0 ), // SPEAKER_TOP_CENTER
|
||||
osd::channel_position( -0.2, 0.5, 1.0 ), // SPEAKER_TOP_FRONT_LEFT
|
||||
osd::channel_position( 0.0, 0.5, 1.0 ), // SPEAKER_TOP_FRONT_CENTER
|
||||
osd::channel_position( 0.2, 0.5, 1.0 ), // SPEAKER_TOP_FRONT_RIGHT
|
||||
osd::channel_position( -0.2, 0.5, -0.5 ), // SPEAKER_TOP_BACK_LEFT
|
||||
osd::channel_position( 0.0, 0.5, -0.5 ), // SPEAKER_TOP_BACK_CENTER
|
||||
osd::channel_position( 0.2, 0.5, -0.5 ) }; // SPEAKER_TOP_BACK_RIGHT
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -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 };
|
||||
static const char *const posname[10] = { "FL", "FR", "FC", "LFE", "BL", "BR", "BC", "SL", "SR", "AUX" };
|
||||
|
||||
static const std::array<double, 3> pos3d[10] = {
|
||||
{ -0.2, 0.0, 1.0 },
|
||||
{ 0.2, 0.0, 1.0 },
|
||||
{ 0.0, 0.0, 1.0 },
|
||||
{ 0.0, -0.5, 1.0 },
|
||||
{ -0.2, 0.0, -0.5 },
|
||||
{ 0.2, 0.0, -0.5 },
|
||||
{ 0.0, 0.0, -0.5 },
|
||||
{ -0.2, 0.0, 0.0 },
|
||||
{ 0.2, 0.0, 0.0 },
|
||||
{ 0.0, 0.0, 10.0 },
|
||||
static const osd::channel_position pos3d[10] = {
|
||||
osd::channel_position::FL,
|
||||
osd::channel_position::FR,
|
||||
osd::channel_position::FC,
|
||||
osd::channel_position::LFE,
|
||||
osd::channel_position::RL,
|
||||
osd::channel_position::RR,
|
||||
osd::channel_position::RC,
|
||||
osd::channel_position(-0.2, 0.0, 0.0),
|
||||
osd::channel_position( 0.2, 0.0, 0.0),
|
||||
osd::channel_position::ONREQ
|
||||
};
|
||||
|
||||
static const uint32_t positions[9][9] = {
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
private:
|
||||
struct position_info {
|
||||
uint32_t m_position;
|
||||
std::array<double, 3> m_coords;
|
||||
osd::channel_position m_coords;
|
||||
};
|
||||
|
||||
static const position_info position_infos[];
|
||||
@ -73,7 +73,7 @@ private:
|
||||
uint32_t m_sinks, m_sources;
|
||||
std::vector<uint32_t> m_position_codes;
|
||||
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;
|
||||
bool m_has_s16;
|
||||
@ -165,16 +165,16 @@ private:
|
||||
// Try to more or less map to speaker.h positions
|
||||
|
||||
const sound_pipewire::position_info sound_pipewire::position_infos[] = {
|
||||
{ SPA_AUDIO_CHANNEL_MONO, { 0.0, 0.0, 1.0 } },
|
||||
{ SPA_AUDIO_CHANNEL_FL, { -0.2, 0.0, 1.0 } },
|
||||
{ SPA_AUDIO_CHANNEL_FR, { 0.2, 0.0, 1.0 } },
|
||||
{ SPA_AUDIO_CHANNEL_FC, { 0.0, 0.0, 1.0 } },
|
||||
{ SPA_AUDIO_CHANNEL_LFE, { 0.0, -0.5, 1.0 } },
|
||||
{ SPA_AUDIO_CHANNEL_RL, { -0.2, 0.0, -0.5 } },
|
||||
{ SPA_AUDIO_CHANNEL_RR, { 0.2, 0.0, -0.5 } },
|
||||
{ SPA_AUDIO_CHANNEL_RC, { 0.0, 0.0, -0.5 } },
|
||||
{ SPA_AUDIO_CHANNEL_AUX0, { 0.0, 0.0, 10.0 } },
|
||||
{ SPA_AUDIO_CHANNEL_UNKNOWN, { 0.0, 0.0, 0.0 } }
|
||||
{ SPA_AUDIO_CHANNEL_MONO, osd::channel_position::FC },
|
||||
{ SPA_AUDIO_CHANNEL_FL, osd::channel_position::FL },
|
||||
{ SPA_AUDIO_CHANNEL_FR, osd::channel_position::FR },
|
||||
{ SPA_AUDIO_CHANNEL_FC, osd::channel_position::FC },
|
||||
{ SPA_AUDIO_CHANNEL_LFE, osd::channel_position::LFE },
|
||||
{ SPA_AUDIO_CHANNEL_RL, osd::channel_position::RL },
|
||||
{ SPA_AUDIO_CHANNEL_RR, osd::channel_position::RR },
|
||||
{ SPA_AUDIO_CHANNEL_RC, osd::channel_position::RC },
|
||||
{ SPA_AUDIO_CHANNEL_AUX0, osd::channel_position::ONREQ },
|
||||
{ SPA_AUDIO_CHANNEL_UNKNOWN, osd::channel_position::UNKNOWN }
|
||||
|
||||
};
|
||||
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
private:
|
||||
struct position_info {
|
||||
pa_channel_position_t m_position;
|
||||
std::array<double, 3> m_coords;
|
||||
osd::channel_position m_coords;
|
||||
};
|
||||
|
||||
static const position_info position_infos[];
|
||||
@ -61,7 +61,7 @@ private:
|
||||
// Audio node info
|
||||
std::vector<pa_channel_position_t> m_position_codes;
|
||||
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;
|
||||
|
||||
osd::audio_rate_range m_rate;
|
||||
@ -122,15 +122,15 @@ private:
|
||||
// Try to more or less map to speaker.h positions
|
||||
|
||||
const sound_pulse::position_info sound_pulse::position_infos[] = {
|
||||
{ PA_CHANNEL_POSITION_MONO, { 0.0, 0.0, 1.0 } },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, { -0.2, 0.0, 1.0 } },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, { 0.2, 0.0, 1.0 } },
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, { 0.0, 0.0, 1.0 } },
|
||||
{ PA_CHANNEL_POSITION_LFE, { 0.0, -0.5, 1.0 } },
|
||||
{ PA_CHANNEL_POSITION_REAR_LEFT, { -0.2, 0.0, -0.5 } },
|
||||
{ PA_CHANNEL_POSITION_REAR_RIGHT, { 0.2, 0.0, -0.5 } },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, { 0.0, 0.0, -0.5 } },
|
||||
{ PA_CHANNEL_POSITION_MAX, { 0.0, 0.0, 10.0 } }
|
||||
{ PA_CHANNEL_POSITION_MONO, osd::channel_position::FC },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, osd::channel_position::FL },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, osd::channel_position::FR },
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, osd::channel_position::FC },
|
||||
{ PA_CHANNEL_POSITION_LFE, osd::channel_position::LFE },
|
||||
{ PA_CHANNEL_POSITION_REAR_LEFT, osd::channel_position::RL },
|
||||
{ PA_CHANNEL_POSITION_REAR_RIGHT, osd::channel_position::RR },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, osd::channel_position::RC },
|
||||
{ PA_CHANNEL_POSITION_MAX, osd::channel_position::ONREQ },
|
||||
};
|
||||
|
||||
|
||||
|
@ -148,17 +148,17 @@ osd::audio_info sound_sdl::get_information()
|
||||
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 std::array<double, 3> pos3d[10] = {
|
||||
{ -0.2, 0.0, 1.0 },
|
||||
{ 0.2, 0.0, 1.0 },
|
||||
{ 0.0, 0.0, 1.0 },
|
||||
{ 0.0, -0.5, 1.0 },
|
||||
{ -0.2, 0.0, -0.5 },
|
||||
{ 0.2, 0.0, -0.5 },
|
||||
{ 0.0, 0.0, -0.5 },
|
||||
{ -0.2, 0.0, 0.0 },
|
||||
{ 0.2, 0.0, 0.0 },
|
||||
{ 0.0, 0.0, 10.0 },
|
||||
static const osd::channel_position pos3d[10] = {
|
||||
osd::channel_position::FL,
|
||||
osd::channel_position::FR,
|
||||
osd::channel_position::FC,
|
||||
osd::channel_position::LFE,
|
||||
osd::channel_position::RL,
|
||||
osd::channel_position::RR,
|
||||
osd::channel_position::RC,
|
||||
osd::channel_position(-0.2, 0.0, 0.0),
|
||||
osd::channel_position( 0.2, 0.0, 0.0),
|
||||
osd::channel_position::ONREQ
|
||||
};
|
||||
|
||||
static const uint32_t positions[8][9] = {
|
||||
|
@ -30,8 +30,8 @@ osd::audio_info sound_module::get_information()
|
||||
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("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(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(osd::channel_position::FR);
|
||||
result.m_streams.resize(1);
|
||||
result.m_streams[0].m_id = 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)
|
||||
{
|
||||
m_delta = 0;
|
||||
m_delta2 = 0;
|
||||
}
|
||||
|
||||
void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept
|
||||
{
|
||||
m_delta -= samples;
|
||||
m_delta2 -= samples;
|
||||
uint32_t pos = 0;
|
||||
while(pos != samples) {
|
||||
if(!m_used_buffers) {
|
||||
m_delta2 += samples - pos;
|
||||
while(pos != samples) {
|
||||
std::copy_n(m_last_sample.data(), m_channels, data);
|
||||
data += m_channels;
|
||||
@ -74,10 +79,13 @@ void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept
|
||||
pos += avail;
|
||||
data += avail * m_channels;
|
||||
}
|
||||
// printf("# %d %d\n", m_delta, m_delta2);
|
||||
}
|
||||
|
||||
void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
|
||||
{
|
||||
m_delta += samples;
|
||||
m_delta2 += samples;
|
||||
auto &buf = push_buffer();
|
||||
buf.m_cpos = 0;
|
||||
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());
|
||||
|
||||
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)
|
||||
for(unsigned i = 0; 10 > i; ++i) {
|
||||
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
|
||||
// to slowly resync to reduce latency (4 seconds to
|
||||
// compensate one buffer, roughly)
|
||||
m_delta2 -= 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
|
||||
|
@ -63,6 +63,7 @@ protected:
|
||||
void pop_buffer() noexcept;
|
||||
buffer &push_buffer();
|
||||
|
||||
int32_t m_delta, m_delta2;
|
||||
uint32_t m_channels;
|
||||
uint32_t m_used_buffers;
|
||||
std::vector<int16_t> m_last_sample;
|
||||
|
Loading…
Reference in New Issue
Block a user