From 4617721c502b2ddaa4e324e86da4997edf738fa5 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 2 Sep 2026 09:55:01 -0400 Subject: ftrace: Synchronize the initialization of ftrace_ops There's some internal state that ftrace_ops needs to have set, but since it can be declared outside of the ftrace.c code, it calls ftrace_ops_init() on the ops in every global function. The issue is that if two tasks call it on the same ops at the same time it is possible to have the initialization of one corrupt the initialization of the other call. Create a ops_mutex to use to synchronize every initialization of the ftrace_ops. The mutex is taken within checking the ftrace_ops flag that states it was initializied but the flag is checked again after the mutex has been taken. Checking first outside the mutex allows it to shortcut having to take the mutex. But then the check needs to be done again after the mute is taken in case of races. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock") Reported-by: sashiko-bot@kernel.org Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/ Signed-off-by: Steven Rostedt --- sound/drivers/opl4/Makefile | 12 + sound/drivers/opl4/opl4_lib.c | 246 ++++++++++ sound/drivers/opl4/opl4_local.h | 235 ++++++++++ sound/drivers/opl4/opl4_mixer.c | 78 ++++ sound/drivers/opl4/opl4_proc.c | 108 +++++ sound/drivers/opl4/opl4_seq.c | 201 +++++++++ sound/drivers/opl4/opl4_synth.c | 620 ++++++++++++++++++++++++++ sound/drivers/opl4/yrw801.c | 961 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 2461 insertions(+) create mode 100644 sound/drivers/opl4/Makefile create mode 100644 sound/drivers/opl4/opl4_lib.c create mode 100644 sound/drivers/opl4/opl4_local.h create mode 100644 sound/drivers/opl4/opl4_mixer.c create mode 100644 sound/drivers/opl4/opl4_proc.c create mode 100644 sound/drivers/opl4/opl4_seq.c create mode 100644 sound/drivers/opl4/opl4_synth.c create mode 100644 sound/drivers/opl4/yrw801.c (limited to 'sound/drivers/opl4') diff --git a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile new file mode 100644 index 000000000..a841630b4 --- /dev/null +++ b/sound/drivers/opl4/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for ALSA +# Copyright (c) 2001 by Jaroslav Kysela +# + +snd-opl4-lib-y := opl4_lib.o opl4_mixer.o +snd-opl4-lib-$(CONFIG_SND_PROC_FS) += opl4_proc.o +snd-opl4-synth-y := opl4_seq.o opl4_synth.o yrw801.o + +obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o +obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-opl4-synth.o diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c new file mode 100644 index 000000000..6364475a3 --- /dev/null +++ b/sound/drivers/opl4/opl4_lib.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Functions for accessing OPL4 devices + * Copyright (c) 2003 by Clemens Ladisch + */ + +#include "opl4_local.h" +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Clemens Ladisch "); +MODULE_DESCRIPTION("OPL4 driver"); +MODULE_LICENSE("GPL"); + +static inline void snd_opl4_wait(struct snd_opl4 *opl4) +{ + int timeout = 10; + while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0) + ; +} + +void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value) +{ + snd_opl4_wait(opl4); + outb(reg, opl4->pcm_port); + + snd_opl4_wait(opl4); + outb(value, opl4->pcm_port + 1); +} + +EXPORT_SYMBOL(snd_opl4_write); + +u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) +{ + snd_opl4_wait(opl4); + outb(reg, opl4->pcm_port); + + snd_opl4_wait(opl4); + return inb(opl4->pcm_port + 1); +} + +EXPORT_SYMBOL(snd_opl4_read); + +void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) +{ + u8 memcfg; + + guard(spinlock_irqsave)(&opl4->reg_lock); + + memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); + snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); + + snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); + snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); + snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); + + snd_opl4_wait(opl4); + outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port); + snd_opl4_wait(opl4); + insb(opl4->pcm_port + 1, buf, size); + + snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); +} + +EXPORT_SYMBOL(snd_opl4_read_memory); + +void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) +{ + u8 memcfg; + + guard(spinlock_irqsave)(&opl4->reg_lock); + + memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); + snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); + + snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); + snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); + snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); + + snd_opl4_wait(opl4); + outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port); + snd_opl4_wait(opl4); + outsb(opl4->pcm_port + 1, buf, size); + + snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); +} + +EXPORT_SYMBOL(snd_opl4_write_memory); + +static void snd_opl4_enable_opl4(struct snd_opl4 *opl4) +{ + outb(OPL3_REG_MODE, opl4->fm_port + 2); + inb(opl4->fm_port); + inb(opl4->fm_port); + outb(OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE, opl4->fm_port + 3); + inb(opl4->fm_port); + inb(opl4->fm_port); +} + +static int snd_opl4_detect(struct snd_opl4 *opl4) +{ + u8 id1, id2; + + snd_opl4_enable_opl4(opl4); + + id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); + dev_dbg(opl4->card->dev, "OPL4[02]=%02x\n", id1); + switch (id1 & OPL4_DEVICE_ID_MASK) { + case 0x20: + opl4->hardware = OPL3_HW_OPL4; + break; + case 0x40: + opl4->hardware = OPL3_HW_OPL4_ML; + break; + default: + return -ENODEV; + } + + snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00); + snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff); + id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM); + id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM); + dev_dbg(opl4->card->dev, "OPL4 id1=%02x id2=%02x\n", id1, id2); + if (id1 != 0x00 || id2 != 0xff) + return -ENODEV; + + snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f); + snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f); + snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00); + return 0; +} + +#if IS_ENABLED(CONFIG_SND_SEQUENCER) +static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev) +{ + struct snd_opl4 *opl4 = seq_dev->private_data; + opl4->seq_dev = NULL; +} + +static int snd_opl4_create_seq_dev(struct snd_opl4 *opl4, int seq_device) +{ + opl4->seq_dev_num = seq_device; + if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4, + sizeof(struct snd_opl4 *), &opl4->seq_dev) >= 0) { + strscpy(opl4->seq_dev->name, "OPL4 Wavetable"); + *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4; + opl4->seq_dev->private_data = opl4; + opl4->seq_dev->private_free = snd_opl4_seq_dev_free; + } + return 0; +} +#endif + +static void snd_opl4_free(struct snd_opl4 *opl4) +{ + snd_opl4_free_proc(opl4); + release_and_free_resource(opl4->res_fm_port); + release_and_free_resource(opl4->res_pcm_port); + kfree(opl4); +} + +static int snd_opl4_dev_free(struct snd_device *device) +{ + struct snd_opl4 *opl4 = device->device_data; + snd_opl4_free(opl4); + return 0; +} + +int snd_opl4_create(struct snd_card *card, + unsigned long fm_port, unsigned long pcm_port, + int seq_device, + struct snd_opl3 **ropl3, struct snd_opl4 **ropl4) +{ + struct snd_opl4 *opl4; + struct snd_opl3 *opl3; + int err; + static const struct snd_device_ops ops = { + .dev_free = snd_opl4_dev_free + }; + + if (ropl3) + *ropl3 = NULL; + if (ropl4) + *ropl4 = NULL; + + opl4 = kzalloc_obj(*opl4); + if (!opl4) + return -ENOMEM; + + opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM"); + opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX"); + if (!opl4->res_fm_port || !opl4->res_pcm_port) { + dev_err(card->dev, "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port); + snd_opl4_free(opl4); + return -EBUSY; + } + + opl4->card = card; + opl4->fm_port = fm_port; + opl4->pcm_port = pcm_port; + spin_lock_init(&opl4->reg_lock); + mutex_init(&opl4->access_mutex); + + err = snd_opl4_detect(opl4); + if (err < 0) { + snd_opl4_free(opl4); + dev_dbg(card->dev, "OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port); + return err; + } + + err = snd_device_new(card, SNDRV_DEV_CODEC, opl4, &ops); + if (err < 0) { + snd_opl4_free(opl4); + return err; + } + + err = snd_opl3_create(card, fm_port, fm_port + 2, opl4->hardware, 1, &opl3); + if (err < 0) { + snd_device_free(card, opl4); + return err; + } + + /* opl3 initialization disabled opl4, so reenable */ + snd_opl4_enable_opl4(opl4); + + snd_opl4_create_mixer(opl4); + snd_opl4_create_proc(opl4); + +#if IS_ENABLED(CONFIG_SND_SEQUENCER) + opl4->seq_client = -1; + if (opl4->hardware < OPL3_HW_OPL4_ML) + snd_opl4_create_seq_dev(opl4, seq_device); +#endif + + if (ropl3) + *ropl3 = opl3; + if (ropl4) + *ropl4 = opl4; + return 0; +} + +EXPORT_SYMBOL(snd_opl4_create); diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h new file mode 100644 index 000000000..a16b4677c --- /dev/null +++ b/sound/drivers/opl4/opl4_local.h @@ -0,0 +1,235 @@ +/* + * Local definitions for the OPL4 driver + * + * Copyright (c) 2003 by Clemens Ladisch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed and/or modified under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __OPL4_LOCAL_H +#define __OPL4_LOCAL_H + +#include + +/* + * Register numbers + */ + +#define OPL4_REG_TEST0 0x00 +#define OPL4_REG_TEST1 0x01 + +#define OPL4_REG_MEMORY_CONFIGURATION 0x02 +#define OPL4_MODE_BIT 0x01 +#define OPL4_MTYPE_BIT 0x02 +#define OPL4_TONE_HEADER_MASK 0x1c +#define OPL4_DEVICE_ID_MASK 0xe0 + +#define OPL4_REG_MEMORY_ADDRESS_HIGH 0x03 +#define OPL4_REG_MEMORY_ADDRESS_MID 0x04 +#define OPL4_REG_MEMORY_ADDRESS_LOW 0x05 +#define OPL4_REG_MEMORY_DATA 0x06 + +/* + * Offsets to the register banks for voices. To get the + * register number just add the voice number to the bank offset. + * + * Wave Table Number low bits (0x08 to 0x1F) + */ +#define OPL4_REG_TONE_NUMBER 0x08 + +/* Wave Table Number high bit, F-Number low bits (0x20 to 0x37) */ +#define OPL4_REG_F_NUMBER 0x20 +#define OPL4_TONE_NUMBER_BIT8 0x01 +#define OPL4_F_NUMBER_LOW_MASK 0xfe + +/* F-Number high bits, Octave, Pseudo-Reverb (0x38 to 0x4F) */ +#define OPL4_REG_OCTAVE 0x38 +#define OPL4_F_NUMBER_HIGH_MASK 0x07 +#define OPL4_BLOCK_MASK 0xf0 +#define OPL4_PSEUDO_REVERB_BIT 0x08 + +/* Total Level, Level Direct (0x50 to 0x67) */ +#define OPL4_REG_LEVEL 0x50 +#define OPL4_TOTAL_LEVEL_MASK 0xfe +#define OPL4_LEVEL_DIRECT_BIT 0x01 + +/* Key On, Damp, LFO RST, CH, Panpot (0x68 to 0x7F) */ +#define OPL4_REG_MISC 0x68 +#define OPL4_KEY_ON_BIT 0x80 +#define OPL4_DAMP_BIT 0x40 +#define OPL4_LFO_RESET_BIT 0x20 +#define OPL4_OUTPUT_CHANNEL_BIT 0x10 +#define OPL4_PAN_POT_MASK 0x0f + +/* LFO, VIB (0x80 to 0x97) */ +#define OPL4_REG_LFO_VIBRATO 0x80 +#define OPL4_LFO_FREQUENCY_MASK 0x38 +#define OPL4_VIBRATO_DEPTH_MASK 0x07 +#define OPL4_CHORUS_SEND_MASK 0xc0 /* ML only */ + +/* Attack / Decay 1 rate (0x98 to 0xAF) */ +#define OPL4_REG_ATTACK_DECAY1 0x98 +#define OPL4_ATTACK_RATE_MASK 0xf0 +#define OPL4_DECAY1_RATE_MASK 0x0f + +/* Decay level / 2 rate (0xB0 to 0xC7) */ +#define OPL4_REG_LEVEL_DECAY2 0xb0 +#define OPL4_DECAY_LEVEL_MASK 0xf0 +#define OPL4_DECAY2_RATE_MASK 0x0f + +/* Release rate / Rate correction (0xC8 to 0xDF) */ +#define OPL4_REG_RELEASE_CORRECTION 0xc8 +#define OPL4_RELEASE_RATE_MASK 0x0f +#define OPL4_RATE_INTERPOLATION_MASK 0xf0 + +/* AM (0xE0 to 0xF7) */ +#define OPL4_REG_TREMOLO 0xe0 +#define OPL4_TREMOLO_DEPTH_MASK 0x07 +#define OPL4_REVERB_SEND_MASK 0xe0 /* ML only */ + +/* Mixer */ +#define OPL4_REG_MIX_CONTROL_FM 0xf8 +#define OPL4_REG_MIX_CONTROL_PCM 0xf9 +#define OPL4_MIX_LEFT_MASK 0x07 +#define OPL4_MIX_RIGHT_MASK 0x38 + +#define OPL4_REG_ATC 0xfa +#define OPL4_ATC_BIT 0x01 /* ???, ML only */ + +/* bits in the OPL3 Status register */ +#define OPL4_STATUS_BUSY 0x01 +#define OPL4_STATUS_LOAD 0x02 + + +#define OPL4_MAX_VOICES 24 + +#define SNDRV_SEQ_DEV_ID_OPL4 "opl4-synth" + + +struct opl4_sound { + u16 tone; + s16 pitch_offset; + u8 key_scaling; + s8 panpot; + u8 vibrato; + u8 tone_attenuate; + u8 volume_factor; + u8 reg_lfo_vibrato; + u8 reg_attack_decay1; + u8 reg_level_decay2; + u8 reg_release_correction; + u8 reg_tremolo; +}; + +struct opl4_region { + u8 key_min, key_max; + struct opl4_sound sound; +}; + +struct opl4_region_ptr { + int count; + const struct opl4_region *regions; +}; + +struct opl4_voice { + struct list_head list; + int number; + struct snd_midi_channel *chan; + int note; + int velocity; + const struct opl4_sound *sound; + u8 level_direct; + u8 reg_f_number; + u8 reg_misc; + u8 reg_lfo_vibrato; +}; + +struct snd_opl4 { + unsigned long fm_port; + unsigned long pcm_port; + struct resource *res_fm_port; + struct resource *res_pcm_port; + unsigned short hardware; + spinlock_t reg_lock; + struct snd_card *card; + +#ifdef CONFIG_SND_PROC_FS + struct snd_info_entry *proc_entry; + int memory_access; +#endif + struct mutex access_mutex; + +#if IS_ENABLED(CONFIG_SND_SEQUENCER) + int used; + + int seq_dev_num; + int seq_client; + struct snd_seq_device *seq_dev; + + struct snd_midi_channel_set *chset; + struct opl4_voice voices[OPL4_MAX_VOICES]; + struct list_head off_voices; + struct list_head on_voices; +#endif +}; + +/* opl4_lib.c */ +void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value); +u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg); +void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size); +void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size); + +/* opl4_mixer.c */ +int snd_opl4_create_mixer(struct snd_opl4 *opl4); + +#ifdef CONFIG_SND_PROC_FS +/* opl4_proc.c */ +int snd_opl4_create_proc(struct snd_opl4 *opl4); +void snd_opl4_free_proc(struct snd_opl4 *opl4); +#else +static inline int snd_opl4_create_proc(struct snd_opl4 *opl4) { return 0; } +static inline void snd_opl4_free_proc(struct snd_opl4 *opl4) {} +#endif + +/* opl4_seq.c */ +extern int volume_boost; + +/* opl4_synth.c */ +void snd_opl4_synth_reset(struct snd_opl4 *opl4); +void snd_opl4_synth_shutdown(struct snd_opl4 *opl4); +void snd_opl4_note_on(void *p, int note, int vel, struct snd_midi_channel *chan); +void snd_opl4_note_off(void *p, int note, int vel, struct snd_midi_channel *chan); +void snd_opl4_terminate_note(void *p, int note, struct snd_midi_channel *chan); +void snd_opl4_control(void *p, int type, struct snd_midi_channel *chan); +void snd_opl4_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset); + +/* yrw801.c */ +int snd_yrw801_detect(struct snd_opl4 *opl4); +extern const struct opl4_region_ptr snd_yrw801_regions[]; + +#endif /* __OPL4_LOCAL_H */ diff --git a/sound/drivers/opl4/opl4_mixer.c b/sound/drivers/opl4/opl4_mixer.c new file mode 100644 index 000000000..deebb8636 --- /dev/null +++ b/sound/drivers/opl4/opl4_mixer.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * OPL4 mixer functions + * Copyright (c) 2003 by Clemens Ladisch + */ + +#include "opl4_local.h" +#include + +static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 7; + return 0; +} + +static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); + u8 reg = kcontrol->private_value; + u8 value; + + guard(spinlock_irqsave)(&opl4->reg_lock); + value = snd_opl4_read(opl4, reg); + ucontrol->value.integer.value[0] = 7 - (value & 7); + ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); + return 0; +} + +static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); + u8 reg = kcontrol->private_value; + u8 value, old_value; + + value = (7 - (ucontrol->value.integer.value[0] & 7)) | + ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); + guard(spinlock_irqsave)(&opl4->reg_lock); + old_value = snd_opl4_read(opl4, reg); + snd_opl4_write(opl4, reg, value); + return value != old_value; +} + +static const struct snd_kcontrol_new snd_opl4_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "FM Playback Volume", + .info = snd_opl4_ctl_info, + .get = snd_opl4_ctl_get, + .put = snd_opl4_ctl_put, + .private_value = OPL4_REG_MIX_CONTROL_FM + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Wavetable Playback Volume", + .info = snd_opl4_ctl_info, + .get = snd_opl4_ctl_get, + .put = snd_opl4_ctl_put, + .private_value = OPL4_REG_MIX_CONTROL_PCM + } +}; + +int snd_opl4_create_mixer(struct snd_opl4 *opl4) +{ + struct snd_card *card = opl4->card; + int i, err; + + strcat(card->mixername, ",OPL4"); + + for (i = 0; i < 2; ++i) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4)); + if (err < 0) + return err; + } + return 0; +} diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c new file mode 100644 index 000000000..fd0ba4704 --- /dev/null +++ b/sound/drivers/opl4/opl4_proc.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Functions for the OPL4 proc file + * Copyright (c) 2003 by Clemens Ladisch + */ + +#include "opl4_local.h" +#include +#include +#include + +static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, + unsigned short mode, void **file_private_data) +{ + struct snd_opl4 *opl4 = entry->private_data; + + guard(mutex)(&opl4->access_mutex); + if (opl4->memory_access) + return -EBUSY; + opl4->memory_access++; + return 0; +} + +static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, + unsigned short mode, void *file_private_data) +{ + struct snd_opl4 *opl4 = entry->private_data; + + guard(mutex)(&opl4->access_mutex); + opl4->memory_access--; + return 0; +} + +static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, char __user *_buf, + size_t count, loff_t pos) +{ + struct snd_opl4 *opl4 = entry->private_data; + char* buf; + + buf = vmalloc(count); + if (!buf) + return -ENOMEM; + snd_opl4_read_memory(opl4, buf, pos, count); + if (copy_to_user(_buf, buf, count)) { + vfree(buf); + return -EFAULT; + } + vfree(buf); + return count; +} + +static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, + void *file_private_data, + struct file *file, + const char __user *_buf, + size_t count, loff_t pos) +{ + struct snd_opl4 *opl4 = entry->private_data; + char *buf; + + buf = vmalloc(count); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, _buf, count)) { + vfree(buf); + return -EFAULT; + } + snd_opl4_write_memory(opl4, buf, pos, count); + vfree(buf); + return count; +} + +static const struct snd_info_entry_ops snd_opl4_mem_proc_ops = { + .open = snd_opl4_mem_proc_open, + .release = snd_opl4_mem_proc_release, + .read = snd_opl4_mem_proc_read, + .write = snd_opl4_mem_proc_write, +}; + +int snd_opl4_create_proc(struct snd_opl4 *opl4) +{ + struct snd_info_entry *entry; + + entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root); + if (entry) { + if (opl4->hardware < OPL3_HW_OPL4_ML) { + /* OPL4 can access 4 MB external ROM/SRAM */ + entry->mode |= 0200; + entry->size = 4 * 1024 * 1024; + } else { + /* OPL4-ML has 1 MB internal ROM */ + entry->size = 1 * 1024 * 1024; + } + entry->content = SNDRV_INFO_CONTENT_DATA; + entry->c.ops = &snd_opl4_mem_proc_ops; + entry->module = THIS_MODULE; + entry->private_data = opl4; + } + opl4->proc_entry = entry; + return 0; +} + +void snd_opl4_free_proc(struct snd_opl4 *opl4) +{ + snd_info_free_entry(opl4->proc_entry); +} diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c new file mode 100644 index 000000000..fd6f15be6 --- /dev/null +++ b/sound/drivers/opl4/opl4_seq.c @@ -0,0 +1,201 @@ +/* + * OPL4 sequencer functions + * + * Copyright (c) 2003 by Clemens Ladisch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed and/or modified under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opl4_local.h" +#include +#include +#include +#include + +MODULE_AUTHOR("Clemens Ladisch "); +MODULE_DESCRIPTION("OPL4 wavetable synth driver"); +MODULE_LICENSE("Dual BSD/GPL"); + +int volume_boost = 8; + +module_param(volume_boost, int, 0644); +MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds."); + +static int snd_opl4_seq_use_inc(struct snd_opl4 *opl4) +{ + if (!try_module_get(opl4->card->module)) + return -EFAULT; + return 0; +} + +static void snd_opl4_seq_use_dec(struct snd_opl4 *opl4) +{ + module_put(opl4->card->module); +} + +static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *info) +{ + struct snd_opl4 *opl4 = private_data; + int err; + + scoped_guard(mutex, &opl4->access_mutex) { + if (opl4->used) + return -EBUSY; + opl4->used++; + + if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { + err = snd_opl4_seq_use_inc(opl4); + if (err < 0) + return err; + } + } + + snd_opl4_synth_reset(opl4); + return 0; +} + +static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe *info) +{ + struct snd_opl4 *opl4 = private_data; + + snd_opl4_synth_shutdown(opl4); + + scoped_guard(mutex, &opl4->access_mutex) { + opl4->used--; + } + + if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) + snd_opl4_seq_use_dec(opl4); + return 0; +} + +static const struct snd_midi_op opl4_ops = { + .note_on = snd_opl4_note_on, + .note_off = snd_opl4_note_off, + .note_terminate = snd_opl4_terminate_note, + .control = snd_opl4_control, + .sysex = snd_opl4_sysex, +}; + +static int snd_opl4_seq_event_input(struct snd_seq_event *ev, int direct, + void *private_data, int atomic, int hop) +{ + struct snd_opl4 *opl4 = private_data; + + snd_midi_process_event(&opl4_ops, ev, opl4->chset); + return 0; +} + +static void snd_opl4_seq_free_port(void *private_data) +{ + struct snd_opl4 *opl4 = private_data; + + snd_midi_channel_free_set(opl4->chset); +} + +static int snd_opl4_seq_probe(struct snd_seq_device *dev) +{ + struct snd_opl4 *opl4; + int client; + struct snd_seq_port_callback pcallbacks; + + opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); + if (!opl4) + return -EINVAL; + + if (snd_yrw801_detect(opl4) < 0) + return -ENODEV; + + opl4->chset = snd_midi_channel_alloc_set(16); + if (!opl4->chset) + return -ENOMEM; + opl4->chset->private_data = opl4; + + /* allocate new client */ + client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num, + "OPL4 Wavetable"); + if (client < 0) { + snd_midi_channel_free_set(opl4->chset); + return client; + } + opl4->seq_client = client; + opl4->chset->client = client; + + /* create new port */ + memset(&pcallbacks, 0, sizeof(pcallbacks)); + pcallbacks.owner = THIS_MODULE; + pcallbacks.use = snd_opl4_seq_use; + pcallbacks.unuse = snd_opl4_seq_unuse; + pcallbacks.event_input = snd_opl4_seq_event_input; + pcallbacks.private_free = snd_opl4_seq_free_port; + pcallbacks.private_data = opl4; + + opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks, + SNDRV_SEQ_PORT_CAP_WRITE | + SNDRV_SEQ_PORT_CAP_SUBS_WRITE, + SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | + SNDRV_SEQ_PORT_TYPE_MIDI_GM | + SNDRV_SEQ_PORT_TYPE_HARDWARE | + SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, + 16, 24, + "OPL4 Wavetable Port"); + if (opl4->chset->port < 0) { + int err = opl4->chset->port; + snd_midi_channel_free_set(opl4->chset); + snd_seq_delete_kernel_client(client); + opl4->seq_client = -1; + return err; + } + return 0; +} + +static void snd_opl4_seq_remove(struct snd_seq_device *dev) +{ + struct snd_opl4 *opl4; + + opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); + if (!opl4) + return; + + if (opl4->seq_client >= 0) { + snd_seq_delete_kernel_client(opl4->seq_client); + opl4->seq_client = -1; + } +} + +static struct snd_seq_driver opl4_seq_driver = { + .probe = snd_opl4_seq_probe, + .remove = snd_opl4_seq_remove, + .driver = { + .name = KBUILD_MODNAME, + }, + .id = SNDRV_SEQ_DEV_ID_OPL4, + .argsize = sizeof(struct snd_opl4 *), +}; + +module_snd_seq_driver(opl4_seq_driver); diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c new file mode 100644 index 000000000..82dbb8519 --- /dev/null +++ b/sound/drivers/opl4/opl4_synth.c @@ -0,0 +1,620 @@ +/* + * OPL4 MIDI synthesizer functions + * + * Copyright (c) 2003 by Clemens Ladisch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed and/or modified under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opl4_local.h" +#include +#include +#include + +/* GM2 controllers */ +#ifndef MIDI_CTL_RELEASE_TIME +#define MIDI_CTL_RELEASE_TIME 0x48 +#define MIDI_CTL_ATTACK_TIME 0x49 +#define MIDI_CTL_DECAY_TIME 0x4b +#define MIDI_CTL_VIBRATO_RATE 0x4c +#define MIDI_CTL_VIBRATO_DEPTH 0x4d +#define MIDI_CTL_VIBRATO_DELAY 0x4e +#endif + +/* + * This table maps 100/128 cents to F_NUMBER. + */ +static const s16 snd_opl4_pitch_map[0x600] = { + 0x000,0x000,0x001,0x001,0x002,0x002,0x003,0x003, + 0x004,0x004,0x005,0x005,0x006,0x006,0x006,0x007, + 0x007,0x008,0x008,0x009,0x009,0x00a,0x00a,0x00b, + 0x00b,0x00c,0x00c,0x00d,0x00d,0x00d,0x00e,0x00e, + 0x00f,0x00f,0x010,0x010,0x011,0x011,0x012,0x012, + 0x013,0x013,0x014,0x014,0x015,0x015,0x015,0x016, + 0x016,0x017,0x017,0x018,0x018,0x019,0x019,0x01a, + 0x01a,0x01b,0x01b,0x01c,0x01c,0x01d,0x01d,0x01e, + 0x01e,0x01e,0x01f,0x01f,0x020,0x020,0x021,0x021, + 0x022,0x022,0x023,0x023,0x024,0x024,0x025,0x025, + 0x026,0x026,0x027,0x027,0x028,0x028,0x029,0x029, + 0x029,0x02a,0x02a,0x02b,0x02b,0x02c,0x02c,0x02d, + 0x02d,0x02e,0x02e,0x02f,0x02f,0x030,0x030,0x031, + 0x031,0x032,0x032,0x033,0x033,0x034,0x034,0x035, + 0x035,0x036,0x036,0x037,0x037,0x038,0x038,0x038, + 0x039,0x039,0x03a,0x03a,0x03b,0x03b,0x03c,0x03c, + 0x03d,0x03d,0x03e,0x03e,0x03f,0x03f,0x040,0x040, + 0x041,0x041,0x042,0x042,0x043,0x043,0x044,0x044, + 0x045,0x045,0x046,0x046,0x047,0x047,0x048,0x048, + 0x049,0x049,0x04a,0x04a,0x04b,0x04b,0x04c,0x04c, + 0x04d,0x04d,0x04e,0x04e,0x04f,0x04f,0x050,0x050, + 0x051,0x051,0x052,0x052,0x053,0x053,0x054,0x054, + 0x055,0x055,0x056,0x056,0x057,0x057,0x058,0x058, + 0x059,0x059,0x05a,0x05a,0x05b,0x05b,0x05c,0x05c, + 0x05d,0x05d,0x05e,0x05e,0x05f,0x05f,0x060,0x060, + 0x061,0x061,0x062,0x062,0x063,0x063,0x064,0x064, + 0x065,0x065,0x066,0x066,0x067,0x067,0x068,0x068, + 0x069,0x069,0x06a,0x06a,0x06b,0x06b,0x06c,0x06c, + 0x06d,0x06d,0x06e,0x06e,0x06f,0x06f,0x070,0x071, + 0x071,0x072,0x072,0x073,0x073,0x074,0x074,0x075, + 0x075,0x076,0x076,0x077,0x077,0x078,0x078,0x079, + 0x079,0x07a,0x07a,0x07b,0x07b,0x07c,0x07c,0x07d, + 0x07d,0x07e,0x07e,0x07f,0x07f,0x080,0x081,0x081, + 0x082,0x082,0x083,0x083,0x084,0x084,0x085,0x085, + 0x086,0x086,0x087,0x087,0x088,0x088,0x089,0x089, + 0x08a,0x08a,0x08b,0x08b,0x08c,0x08d,0x08d,0x08e, + 0x08e,0x08f,0x08f,0x090,0x090,0x091,0x091,0x092, + 0x092,0x093,0x093,0x094,0x094,0x095,0x096,0x096, + 0x097,0x097,0x098,0x098,0x099,0x099,0x09a,0x09a, + 0x09b,0x09b,0x09c,0x09c,0x09d,0x09d,0x09e,0x09f, + 0x09f,0x0a0,0x0a0,0x0a1,0x0a1,0x0a2,0x0a2,0x0a3, + 0x0a3,0x0a4,0x0a4,0x0a5,0x0a6,0x0a6,0x0a7,0x0a7, + 0x0a8,0x0a8,0x0a9,0x0a9,0x0aa,0x0aa,0x0ab,0x0ab, + 0x0ac,0x0ad,0x0ad,0x0ae,0x0ae,0x0af,0x0af,0x0b0, + 0x0b0,0x0b1,0x0b1,0x0b2,0x0b2,0x0b3,0x0b4,0x0b4, + 0x0b5,0x0b5,0x0b6,0x0b6,0x0b7,0x0b7,0x0b8,0x0b8, + 0x0b9,0x0ba,0x0ba,0x0bb,0x0bb,0x0bc,0x0bc,0x0bd, + 0x0bd,0x0be,0x0be,0x0bf,0x0c0,0x0c0,0x0c1,0x0c1, + 0x0c2,0x0c2,0x0c3,0x0c3,0x0c4,0x0c4,0x0c5,0x0c6, + 0x0c6,0x0c7,0x0c7,0x0c8,0x0c8,0x0c9,0x0c9,0x0ca, + 0x0cb,0x0cb,0x0cc,0x0cc,0x0cd,0x0cd,0x0ce,0x0ce, + 0x0cf,0x0d0,0x0d0,0x0d1,0x0d1,0x0d2,0x0d2,0x0d3, + 0x0d3,0x0d4,0x0d5,0x0d5,0x0d6,0x0d6,0x0d7,0x0d7, + 0x0d8,0x0d8,0x0d9,0x0da,0x0da,0x0db,0x0db,0x0dc, + 0x0dc,0x0dd,0x0de,0x0de,0x0df,0x0df,0x0e0,0x0e0, + 0x0e1,0x0e1,0x0e2,0x0e3,0x0e3,0x0e4,0x0e4,0x0e5, + 0x0e5,0x0e6,0x0e7,0x0e7,0x0e8,0x0e8,0x0e9,0x0e9, + 0x0ea,0x0eb,0x0eb,0x0ec,0x0ec,0x0ed,0x0ed,0x0ee, + 0x0ef,0x0ef,0x0f0,0x0f0,0x0f1,0x0f1,0x0f2,0x0f3, + 0x0f3,0x0f4,0x0f4,0x0f5,0x0f5,0x0f6,0x0f7,0x0f7, + 0x0f8,0x0f8,0x0f9,0x0f9,0x0fa,0x0fb,0x0fb,0x0fc, + 0x0fc,0x0fd,0x0fd,0x0fe,0x0ff,0x0ff,0x100,0x100, + 0x101,0x101,0x102,0x103,0x103,0x104,0x104,0x105, + 0x106,0x106,0x107,0x107,0x108,0x108,0x109,0x10a, + 0x10a,0x10b,0x10b,0x10c,0x10c,0x10d,0x10e,0x10e, + 0x10f,0x10f,0x110,0x111,0x111,0x112,0x112,0x113, + 0x114,0x114,0x115,0x115,0x116,0x116,0x117,0x118, + 0x118,0x119,0x119,0x11a,0x11b,0x11b,0x11c,0x11c, + 0x11d,0x11e,0x11e,0x11f,0x11f,0x120,0x120,0x121, + 0x122,0x122,0x123,0x123,0x124,0x125,0x125,0x126, + 0x126,0x127,0x128,0x128,0x129,0x129,0x12a,0x12b, + 0x12b,0x12c,0x12c,0x12d,0x12e,0x12e,0x12f,0x12f, + 0x130,0x131,0x131,0x132,0x132,0x133,0x134,0x134, + 0x135,0x135,0x136,0x137,0x137,0x138,0x138,0x139, + 0x13a,0x13a,0x13b,0x13b,0x13c,0x13d,0x13d,0x13e, + 0x13e,0x13f,0x140,0x140,0x141,0x141,0x142,0x143, + 0x143,0x144,0x144,0x145,0x146,0x146,0x147,0x148, + 0x148,0x149,0x149,0x14a,0x14b,0x14b,0x14c,0x14c, + 0x14d,0x14e,0x14e,0x14f,0x14f,0x150,0x151,0x151, + 0x152,0x153,0x153,0x154,0x154,0x155,0x156,0x156, + 0x157,0x157,0x158,0x159,0x159,0x15a,0x15b,0x15b, + 0x15c,0x15c,0x15d,0x15e,0x15e,0x15f,0x160,0x160, + 0x161,0x161,0x162,0x163,0x163,0x164,0x165,0x165, + 0x166,0x166,0x167,0x168,0x168,0x169,0x16a,0x16a, + 0x16b,0x16b,0x16c,0x16d,0x16d,0x16e,0x16f,0x16f, + 0x170,0x170,0x171,0x172,0x172,0x173,0x174,0x174, + 0x175,0x175,0x176,0x177,0x177,0x178,0x179,0x179, + 0x17a,0x17a,0x17b,0x17c,0x17c,0x17d,0x17e,0x17e, + 0x17f,0x180,0x180,0x181,0x181,0x182,0x183,0x183, + 0x184,0x185,0x185,0x186,0x187,0x187,0x188,0x188, + 0x189,0x18a,0x18a,0x18b,0x18c,0x18c,0x18d,0x18e, + 0x18e,0x18f,0x190,0x190,0x191,0x191,0x192,0x193, + 0x193,0x194,0x195,0x195,0x196,0x197,0x197,0x198, + 0x199,0x199,0x19a,0x19a,0x19b,0x19c,0x19c,0x19d, + 0x19e,0x19e,0x19f,0x1a0,0x1a0,0x1a1,0x1a2,0x1a2, + 0x1a3,0x1a4,0x1a4,0x1a5,0x1a6,0x1a6,0x1a7,0x1a8, + 0x1a8,0x1a9,0x1a9,0x1aa,0x1ab,0x1ab,0x1ac,0x1ad, + 0x1ad,0x1ae,0x1af,0x1af,0x1b0,0x1b1,0x1b1,0x1b2, + 0x1b3,0x1b3,0x1b4,0x1b5,0x1b5,0x1b6,0x1b7,0x1b7, + 0x1b8,0x1b9,0x1b9,0x1ba,0x1bb,0x1bb,0x1bc,0x1bd, + 0x1bd,0x1be,0x1bf,0x1bf,0x1c0,0x1c1,0x1c1,0x1c2, + 0x1c3,0x1c3,0x1c4,0x1c5,0x1c5,0x1c6,0x1c7,0x1c7, + 0x1c8,0x1c9,0x1c9,0x1ca,0x1cb,0x1cb,0x1cc,0x1cd, + 0x1cd,0x1ce,0x1cf,0x1cf,0x1d0,0x1d1,0x1d1,0x1d2, + 0x1d3,0x1d3,0x1d4,0x1d5,0x1d5,0x1d6,0x1d7,0x1d7, + 0x1d8,0x1d9,0x1d9,0x1da,0x1db,0x1db,0x1dc,0x1dd, + 0x1dd,0x1de,0x1df,0x1df,0x1e0,0x1e1,0x1e1,0x1e2, + 0x1e3,0x1e4,0x1e4,0x1e5,0x1e6,0x1e6,0x1e7,0x1e8, + 0x1e8,0x1e9,0x1ea,0x1ea,0x1eb,0x1ec,0x1ec,0x1ed, + 0x1ee,0x1ee,0x1ef,0x1f0,0x1f0,0x1f1,0x1f2,0x1f3, + 0x1f3,0x1f4,0x1f5,0x1f5,0x1f6,0x1f7,0x1f7,0x1f8, + 0x1f9,0x1f9,0x1fa,0x1fb,0x1fb,0x1fc,0x1fd,0x1fe, + 0x1fe,0x1ff,0x200,0x200,0x201,0x202,0x202,0x203, + 0x204,0x205,0x205,0x206,0x207,0x207,0x208,0x209, + 0x209,0x20a,0x20b,0x20b,0x20c,0x20d,0x20e,0x20e, + 0x20f,0x210,0x210,0x211,0x212,0x212,0x213,0x214, + 0x215,0x215,0x216,0x217,0x217,0x218,0x219,0x21a, + 0x21a,0x21b,0x21c,0x21c,0x21d,0x21e,0x21e,0x21f, + 0x220,0x221,0x221,0x222,0x223,0x223,0x224,0x225, + 0x226,0x226,0x227,0x228,0x228,0x229,0x22a,0x22b, + 0x22b,0x22c,0x22d,0x22d,0x22e,0x22f,0x230,0x230, + 0x231,0x232,0x232,0x233,0x234,0x235,0x235,0x236, + 0x237,0x237,0x238,0x239,0x23a,0x23a,0x23b,0x23c, + 0x23c,0x23d,0x23e,0x23f,0x23f,0x240,0x241,0x241, + 0x242,0x243,0x244,0x244,0x245,0x246,0x247,0x247, + 0x248,0x249,0x249,0x24a,0x24b,0x24c,0x24c,0x24d, + 0x24e,0x24f,0x24f,0x250,0x251,0x251,0x252,0x253, + 0x254,0x254,0x255,0x256,0x257,0x257,0x258,0x259, + 0x259,0x25a,0x25b,0x25c,0x25c,0x25d,0x25e,0x25f, + 0x25f,0x260,0x261,0x262,0x262,0x263,0x264,0x265, + 0x265,0x266,0x267,0x267,0x268,0x269,0x26a,0x26a, + 0x26b,0x26c,0x26d,0x26d,0x26e,0x26f,0x270,0x270, + 0x271,0x272,0x273,0x273,0x274,0x275,0x276,0x276, + 0x277,0x278,0x279,0x279,0x27a,0x27b,0x27c,0x27c, + 0x27d,0x27e,0x27f,0x27f,0x280,0x281,0x282,0x282, + 0x283,0x284,0x285,0x285,0x286,0x287,0x288,0x288, + 0x289,0x28a,0x28b,0x28b,0x28c,0x28d,0x28e,0x28e, + 0x28f,0x290,0x291,0x291,0x292,0x293,0x294,0x294, + 0x295,0x296,0x297,0x298,0x298,0x299,0x29a,0x29b, + 0x29b,0x29c,0x29d,0x29e,0x29e,0x29f,0x2a0,0x2a1, + 0x2a1,0x2a2,0x2a3,0x2a4,0x2a5,0x2a5,0x2a6,0x2a7, + 0x2a8,0x2a8,0x2a9,0x2aa,0x2ab,0x2ab,0x2ac,0x2ad, + 0x2ae,0x2af,0x2af,0x2b0,0x2b1,0x2b2,0x2b2,0x2b3, + 0x2b4,0x2b5,0x2b5,0x2b6,0x2b7,0x2b8,0x2b9,0x2b9, + 0x2ba,0x2bb,0x2bc,0x2bc,0x2bd,0x2be,0x2bf,0x2c0, + 0x2c0,0x2c1,0x2c2,0x2c3,0x2c4,0x2c4,0x2c5,0x2c6, + 0x2c7,0x2c7,0x2c8,0x2c9,0x2ca,0x2cb,0x2cb,0x2cc, + 0x2cd,0x2ce,0x2ce,0x2cf,0x2d0,0x2d1,0x2d2,0x2d2, + 0x2d3,0x2d4,0x2d5,0x2d6,0x2d6,0x2d7,0x2d8,0x2d9, + 0x2da,0x2da,0x2db,0x2dc,0x2dd,0x2dd,0x2de,0x2df, + 0x2e0,0x2e1,0x2e1,0x2e2,0x2e3,0x2e4,0x2e5,0x2e5, + 0x2e6,0x2e7,0x2e8,0x2e9,0x2e9,0x2ea,0x2eb,0x2ec, + 0x2ed,0x2ed,0x2ee,0x2ef,0x2f0,0x2f1,0x2f1,0x2f2, + 0x2f3,0x2f4,0x2f5,0x2f5,0x2f6,0x2f7,0x2f8,0x2f9, + 0x2f9,0x2fa,0x2fb,0x2fc,0x2fd,0x2fd,0x2fe,0x2ff, + 0x300,0x301,0x302,0x302,0x303,0x304,0x305,0x306, + 0x306,0x307,0x308,0x309,0x30a,0x30a,0x30b,0x30c, + 0x30d,0x30e,0x30f,0x30f,0x310,0x311,0x312,0x313, + 0x313,0x314,0x315,0x316,0x317,0x318,0x318,0x319, + 0x31a,0x31b,0x31c,0x31c,0x31d,0x31e,0x31f,0x320, + 0x321,0x321,0x322,0x323,0x324,0x325,0x326,0x326, + 0x327,0x328,0x329,0x32a,0x32a,0x32b,0x32c,0x32d, + 0x32e,0x32f,0x32f,0x330,0x331,0x332,0x333,0x334, + 0x334,0x335,0x336,0x337,0x338,0x339,0x339,0x33a, + 0x33b,0x33c,0x33d,0x33e,0x33e,0x33f,0x340,0x341, + 0x342,0x343,0x343,0x344,0x345,0x346,0x347,0x348, + 0x349,0x349,0x34a,0x34b,0x34c,0x34d,0x34e,0x34e, + 0x34f,0x350,0x351,0x352,0x353,0x353,0x354,0x355, + 0x356,0x357,0x358,0x359,0x359,0x35a,0x35b,0x35c, + 0x35d,0x35e,0x35f,0x35f,0x360,0x361,0x362,0x363, + 0x364,0x364,0x365,0x366,0x367,0x368,0x369,0x36a, + 0x36a,0x36b,0x36c,0x36d,0x36e,0x36f,0x370,0x370, + 0x371,0x372,0x373,0x374,0x375,0x376,0x377,0x377, + 0x378,0x379,0x37a,0x37b,0x37c,0x37d,0x37d,0x37e, + 0x37f,0x380,0x381,0x382,0x383,0x383,0x384,0x385, + 0x386,0x387,0x388,0x389,0x38a,0x38a,0x38b,0x38c, + 0x38d,0x38e,0x38f,0x390,0x391,0x391,0x392,0x393, + 0x394,0x395,0x396,0x397,0x398,0x398,0x399,0x39a, + 0x39b,0x39c,0x39d,0x39e,0x39f,0x39f,0x3a0,0x3a1, + 0x3a2,0x3a3,0x3a4,0x3a5,0x3a6,0x3a7,0x3a7,0x3a8, + 0x3a9,0x3aa,0x3ab,0x3ac,0x3ad,0x3ae,0x3ae,0x3af, + 0x3b0,0x3b1,0x3b2,0x3b3,0x3b4,0x3b5,0x3b6,0x3b6, + 0x3b7,0x3b8,0x3b9,0x3ba,0x3bb,0x3bc,0x3bd,0x3be, + 0x3bf,0x3bf,0x3c0,0x3c1,0x3c2,0x3c3,0x3c4,0x3c5, + 0x3c6,0x3c7,0x3c7,0x3c8,0x3c9,0x3ca,0x3cb,0x3cc, + 0x3cd,0x3ce,0x3cf,0x3d0,0x3d1,0x3d1,0x3d2,0x3d3, + 0x3d4,0x3d5,0x3d6,0x3d7,0x3d8,0x3d9,0x3da,0x3da, + 0x3db,0x3dc,0x3dd,0x3de,0x3df,0x3e0,0x3e1,0x3e2, + 0x3e3,0x3e4,0x3e4,0x3e5,0x3e6,0x3e7,0x3e8,0x3e9, + 0x3ea,0x3eb,0x3ec,0x3ed,0x3ee,0x3ef,0x3ef,0x3f0, + 0x3f1,0x3f2,0x3f3,0x3f4,0x3f5,0x3f6,0x3f7,0x3f8, + 0x3f9,0x3fa,0x3fa,0x3fb,0x3fc,0x3fd,0x3fe,0x3ff +}; + +/* + * Attenuation according to GM recommendations, in -0.375 dB units. + * table[v] = 40 * log(v / 127) / -0.375 + */ +static const unsigned char snd_opl4_volume_table[128] = { + 255,224,192,173,160,150,141,134, + 128,122,117,113,109,105,102, 99, + 96, 93, 90, 88, 85, 83, 81, 79, + 77, 75, 73, 71, 70, 68, 67, 65, + 64, 62, 61, 59, 58, 57, 56, 54, + 53, 52, 51, 50, 49, 48, 47, 46, + 45, 44, 43, 42, 41, 40, 39, 39, + 38, 37, 36, 35, 34, 34, 33, 32, + 31, 31, 30, 29, 29, 28, 27, 27, + 26, 25, 25, 24, 24, 23, 22, 22, + 21, 21, 20, 19, 19, 18, 18, 17, + 17, 16, 16, 15, 15, 14, 14, 13, + 13, 12, 12, 11, 11, 10, 10, 9, + 9, 9, 8, 8, 7, 7, 6, 6, + 6, 5, 5, 4, 4, 4, 3, 3, + 2, 2, 2, 1, 1, 0, 0, 0 +}; + +/* + * Initializes all voices. + */ +void snd_opl4_synth_reset(struct snd_opl4 *opl4) +{ + int i; + + scoped_guard(spinlock_irqsave, &opl4->reg_lock) { + for (i = 0; i < OPL4_MAX_VOICES; i++) + snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT); + } + + INIT_LIST_HEAD(&opl4->off_voices); + INIT_LIST_HEAD(&opl4->on_voices); + memset(opl4->voices, 0, sizeof(opl4->voices)); + for (i = 0; i < OPL4_MAX_VOICES; i++) { + opl4->voices[i].number = i; + list_add_tail(&opl4->voices[i].list, &opl4->off_voices); + } + + snd_midi_channel_set_clear(opl4->chset); +} + +/* + * Shuts down all voices. + */ +void snd_opl4_synth_shutdown(struct snd_opl4 *opl4) +{ + int i; + + guard(spinlock_irqsave)(&opl4->reg_lock); + for (i = 0; i < OPL4_MAX_VOICES; i++) + snd_opl4_write(opl4, OPL4_REG_MISC + i, + opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT); +} + +/* + * Executes the callback for all voices playing the specified note. + */ +static void snd_opl4_do_for_note(struct snd_opl4 *opl4, int note, struct snd_midi_channel *chan, + void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) +{ + int i; + struct opl4_voice *voice; + + guard(spinlock_irqsave)(&opl4->reg_lock); + for (i = 0; i < OPL4_MAX_VOICES; i++) { + voice = &opl4->voices[i]; + if (voice->chan == chan && voice->note == note) { + func(opl4, voice); + } + } +} + +/* + * Executes the callback for all voices of to the specified channel. + */ +static void snd_opl4_do_for_channel(struct snd_opl4 *opl4, + struct snd_midi_channel *chan, + void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) +{ + int i; + struct opl4_voice *voice; + + guard(spinlock_irqsave)(&opl4->reg_lock); + for (i = 0; i < OPL4_MAX_VOICES; i++) { + voice = &opl4->voices[i]; + if (voice->chan == chan) { + func(opl4, voice); + } + } +} + +/* + * Executes the callback for all active voices. + */ +static void snd_opl4_do_for_all(struct snd_opl4 *opl4, + void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) +{ + int i; + struct opl4_voice *voice; + + guard(spinlock_irqsave)(&opl4->reg_lock); + for (i = 0; i < OPL4_MAX_VOICES; i++) { + voice = &opl4->voices[i]; + if (voice->chan) + func(opl4, voice); + } +} + +static void snd_opl4_update_volume(struct snd_opl4 *opl4, struct opl4_voice *voice) +{ + int att; + + att = voice->sound->tone_attenuate; + att += snd_opl4_volume_table[opl4->chset->gs_master_volume & 0x7f]; + att += snd_opl4_volume_table[voice->chan->gm_volume & 0x7f]; + att += snd_opl4_volume_table[voice->chan->gm_expression & 0x7f]; + att += snd_opl4_volume_table[voice->velocity]; + att = 0x7f - (0x7f - att) * (voice->sound->volume_factor) / 0xfe - volume_boost; + if (att < 0) + att = 0; + else if (att > 0x7e) + att = 0x7e; + snd_opl4_write(opl4, OPL4_REG_LEVEL + voice->number, + (att << 1) | voice->level_direct); + voice->level_direct = 0; +} + +static void snd_opl4_update_pan(struct snd_opl4 *opl4, struct opl4_voice *voice) +{ + int pan = voice->sound->panpot; + + if (!voice->chan->drum_channel) + pan += (voice->chan->control[MIDI_CTL_MSB_PAN] - 0x40) >> 3; + if (pan < -7) + pan = -7; + else if (pan > 7) + pan = 7; + voice->reg_misc = (voice->reg_misc & ~OPL4_PAN_POT_MASK) + | (pan & OPL4_PAN_POT_MASK); + snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); +} + +static void snd_opl4_update_vibrato_depth(struct snd_opl4 *opl4, + struct opl4_voice *voice) +{ + int depth; + + if (voice->chan->drum_channel) + return; + depth = (7 - voice->sound->vibrato) + * (voice->chan->control[MIDI_CTL_VIBRATO_DEPTH] & 0x7f); + depth = (depth >> 7) + voice->sound->vibrato; + voice->reg_lfo_vibrato &= ~OPL4_VIBRATO_DEPTH_MASK; + voice->reg_lfo_vibrato |= depth & OPL4_VIBRATO_DEPTH_MASK; + snd_opl4_write(opl4, OPL4_REG_LFO_VIBRATO + voice->number, + voice->reg_lfo_vibrato); +} + +static void snd_opl4_update_pitch(struct snd_opl4 *opl4, + struct opl4_voice *voice) +{ + struct snd_midi_channel *chan = voice->chan; + int note, pitch, octave; + + note = chan->drum_channel ? 60 : voice->note; + /* + * pitch is in 100/128 cents, so 0x80 is one semitone and + * 0x600 is one octave. + */ + pitch = ((note - 60) << 7) * voice->sound->key_scaling / 100 + (60 << 7); + pitch += voice->sound->pitch_offset; + if (!chan->drum_channel) + pitch += chan->gm_rpn_coarse_tuning; + pitch += chan->gm_rpn_fine_tuning >> 7; + pitch += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 0x2000; + if (pitch < 0) + pitch = 0; + else if (pitch >= 0x6000) + pitch = 0x5fff; + octave = pitch / 0x600 - 8; + pitch = snd_opl4_pitch_map[pitch % 0x600]; + + snd_opl4_write(opl4, OPL4_REG_OCTAVE + voice->number, + (octave << 4) | ((pitch >> 7) & OPL4_F_NUMBER_HIGH_MASK)); + voice->reg_f_number = (voice->reg_f_number & OPL4_TONE_NUMBER_BIT8) + | ((pitch << 1) & OPL4_F_NUMBER_LOW_MASK); + snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice->number, voice->reg_f_number); +} + +static void snd_opl4_update_tone_parameters(struct snd_opl4 *opl4, + struct opl4_voice *voice) +{ + snd_opl4_write(opl4, OPL4_REG_ATTACK_DECAY1 + voice->number, + voice->sound->reg_attack_decay1); + snd_opl4_write(opl4, OPL4_REG_LEVEL_DECAY2 + voice->number, + voice->sound->reg_level_decay2); + snd_opl4_write(opl4, OPL4_REG_RELEASE_CORRECTION + voice->number, + voice->sound->reg_release_correction); + snd_opl4_write(opl4, OPL4_REG_TREMOLO + voice->number, + voice->sound->reg_tremolo); +} + +/* allocate one voice */ +static struct opl4_voice *snd_opl4_get_voice(struct snd_opl4 *opl4) +{ + /* first, try to get the oldest key-off voice */ + if (!list_empty(&opl4->off_voices)) + return list_entry(opl4->off_voices.next, struct opl4_voice, list); + /* then get the oldest key-on voice */ + snd_BUG_ON(list_empty(&opl4->on_voices)); + return list_entry(opl4->on_voices.next, struct opl4_voice, list); +} + +static void snd_opl4_wait_for_wave_headers(struct snd_opl4 *opl4) +{ + int timeout = 200; + + while ((inb(opl4->fm_port) & OPL4_STATUS_LOAD) && --timeout > 0) + udelay(10); +} + +void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_channel *chan) +{ + struct snd_opl4 *opl4 = private_data; + const struct opl4_region_ptr *regions; + struct opl4_voice *voice[2]; + const struct opl4_sound *sound[2]; + int voices = 0, i; + + /* determine the number of voices and voice parameters */ + i = chan->drum_channel ? 0x80 : (chan->midi_program & 0x7f); + regions = &snd_yrw801_regions[i]; + for (i = 0; i < regions->count; i++) { + if (note >= regions->regions[i].key_min && + note <= regions->regions[i].key_max) { + sound[voices] = ®ions->regions[i].sound; + if (++voices >= 2) + break; + } + } + + /* allocate and initialize the needed voices */ + scoped_guard(spinlock_irqsave, &opl4->reg_lock) { + for (i = 0; i < voices; i++) { + voice[i] = snd_opl4_get_voice(opl4); + list_move_tail(&voice[i]->list, &opl4->on_voices); + voice[i]->chan = chan; + voice[i]->note = note; + voice[i]->velocity = vel & 0x7f; + voice[i]->sound = sound[i]; + } + + /* set tone number (triggers header loading) */ + for (i = 0; i < voices; i++) { + voice[i]->reg_f_number = + (sound[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8; + snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice[i]->number, + voice[i]->reg_f_number); + snd_opl4_write(opl4, OPL4_REG_TONE_NUMBER + voice[i]->number, + sound[i]->tone & 0xff); + } + + /* set parameters which can be set while loading */ + for (i = 0; i < voices; i++) { + voice[i]->reg_misc = OPL4_LFO_RESET_BIT; + snd_opl4_update_pan(opl4, voice[i]); + snd_opl4_update_pitch(opl4, voice[i]); + voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT; + snd_opl4_update_volume(opl4, voice[i]); + } + } + + /* wait for completion of loading */ + snd_opl4_wait_for_wave_headers(opl4); + + /* set remaining parameters */ + guard(spinlock_irqsave)(&opl4->reg_lock); + for (i = 0; i < voices; i++) { + snd_opl4_update_tone_parameters(opl4, voice[i]); + voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato; + snd_opl4_update_vibrato_depth(opl4, voice[i]); + } + + /* finally, switch on all voices */ + for (i = 0; i < voices; i++) { + voice[i]->reg_misc = + (voice[i]->reg_misc & 0x1f) | OPL4_KEY_ON_BIT; + snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number, + voice[i]->reg_misc); + } +} + +static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice) +{ + list_move_tail(&voice->list, &opl4->off_voices); + + voice->reg_misc &= ~OPL4_KEY_ON_BIT; + snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); +} + +void snd_opl4_note_off(void *private_data, int note, int vel, struct snd_midi_channel *chan) +{ + struct snd_opl4 *opl4 = private_data; + + snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off); +} + +static void snd_opl4_terminate_voice(struct snd_opl4 *opl4, struct opl4_voice *voice) +{ + list_move_tail(&voice->list, &opl4->off_voices); + + voice->reg_misc = (voice->reg_misc & ~OPL4_KEY_ON_BIT) | OPL4_DAMP_BIT; + snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); +} + +void snd_opl4_terminate_note(void *private_data, int note, struct snd_midi_channel *chan) +{ + struct snd_opl4 *opl4 = private_data; + + snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice); +} + +void snd_opl4_control(void *private_data, int type, struct snd_midi_channel *chan) +{ + struct snd_opl4 *opl4 = private_data; + + switch (type) { + case MIDI_CTL_MSB_MODWHEEL: + chan->control[MIDI_CTL_VIBRATO_DEPTH] = chan->control[MIDI_CTL_MSB_MODWHEEL]; + snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth); + break; + case MIDI_CTL_MSB_MAIN_VOLUME: + snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume); + break; + case MIDI_CTL_MSB_PAN: + snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pan); + break; + case MIDI_CTL_MSB_EXPRESSION: + snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume); + break; + case MIDI_CTL_VIBRATO_RATE: + /* not yet supported */ + break; + case MIDI_CTL_VIBRATO_DEPTH: + snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth); + break; + case MIDI_CTL_VIBRATO_DELAY: + /* not yet supported */ + break; + case MIDI_CTL_E1_REVERB_DEPTH: + /* + * Each OPL4 voice has a bit called "Pseudo-Reverb", but + * IMHO _not_ using it enhances the listening experience. + */ + break; + case MIDI_CTL_PITCHBEND: + snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pitch); + break; + } +} + +void snd_opl4_sysex(void *private_data, unsigned char *buf, int len, + int parsed, struct snd_midi_channel_set *chset) +{ + struct snd_opl4 *opl4 = private_data; + + if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME) + snd_opl4_do_for_all(opl4, snd_opl4_update_volume); +} diff --git a/sound/drivers/opl4/yrw801.c b/sound/drivers/opl4/yrw801.c new file mode 100644 index 000000000..9e464b84b --- /dev/null +++ b/sound/drivers/opl4/yrw801.c @@ -0,0 +1,961 @@ +/* + * Information about the Yamaha YRW801 wavetable ROM chip + * + * Copyright (c) 2003 by Clemens Ladisch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed and/or modified under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opl4_local.h" + +int snd_yrw801_detect(struct snd_opl4 *opl4) +{ + char buf[15]; + + snd_opl4_read_memory(opl4, buf, 0x001200, 15); + if (memcmp(buf, "CopyrightYAMAHA", 15)) + return -ENODEV; + snd_opl4_read_memory(opl4, buf, 0x1ffffe, 2); + if (buf[0] != 0x01) + return -ENODEV; + dev_dbg(opl4->card->dev, "YRW801 ROM version %02x.%02x\n", buf[0], buf[1]); + return 0; +} + +/* + * The instrument definitions are stored statically because, in practice, the + * OPL4 is always coupled with a YRW801. Dynamic instrument loading would be + * required if downloading sample data to external SRAM was actually supported + * by this driver. + */ + +static const struct opl4_region regions_00[] = { /* Acoustic Grand Piano */ + {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}}, + {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xc8,0x20,0xf2,0x14,0x18,0x0}}, + {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xc8,0x20,0xf3,0x14,0x18,0x0}}, + {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}} +}; +static const struct opl4_region regions_01[] = { /* Bright Acoustic Piano */ + {0x14, 0x2d, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}}, + {0x2e, 0x33, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x34, 0x39, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x3a, 0x3f, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x40, 0x45, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x46, 0x4b, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x4c, 0x52, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}}, + {0x53, 0x58, {0x133,2081,100, 0,0,0x07,0xc8,0x20,0xf2,0x14,0x18,0x0}}, + {0x59, 0x5e, {0x134,1444,100, 0,0,0x0a,0xc8,0x20,0xf3,0x14,0x18,0x0}}, + {0x5f, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}} +}; +static const struct opl4_region regions_02[] = { /* Electric Grand Piano */ + {0x14, 0x2d, {0x12c,7476,100, 1,0,0x00,0xae,0x20,0xf2,0x13,0x07,0x0}}, + {0x2e, 0x33, {0x12d,6818,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, + {0x34, 0x39, {0x12e,5901,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, + {0x3a, 0x3f, {0x12f,5292,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, + {0x40, 0x45, {0x130,4262,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, + {0x46, 0x4b, {0x131,3627,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, + {0x4c, 0x52, {0x132,3118,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, + {0x53, 0x58, {0x133,2083,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x17,0x0}}, + {0x59, 0x5e, {0x134,1446,100, 1,0,0x00,0xae,0x20,0xf3,0x14,0x17,0x0}}, + {0x5f, 0x6d, {0x135,1917,100, 1,0,0x00,0xae,0x20,0xf4,0x15,0x07,0x0}}, + {0x00, 0x7f, {0x06c,6375,100,-1,0,0x00,0xc2,0x28,0xf4,0x23,0x18,0x0}} +}; +static const struct opl4_region regions_03[] = { /* Honky-Tonk Piano */ + {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}}, + {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xb4,0x20,0xf2,0x14,0x18,0x0}}, + {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xb4,0x20,0xf3,0x14,0x18,0x0}}, + {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}}, + {0x14, 0x27, {0x12c,7486,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}}, + {0x28, 0x2d, {0x12d,6803,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x2e, 0x33, {0x12e,5912,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x34, 0x39, {0x12f,5275,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x3a, 0x3f, {0x130,4274,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x40, 0x45, {0x131,3611,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x46, 0x4b, {0x132,3129,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}}, + {0x4c, 0x52, {0x133,2074,100, 0,0,0x07,0xb4,0x20,0xf2,0x14,0x18,0x0}}, + {0x53, 0x58, {0x134,1457,100, 0,0,0x01,0xb4,0x20,0xf3,0x14,0x18,0x0}}, + {0x59, 0x6d, {0x135,1903,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}} +}; +static const struct opl4_region regions_04[] = { /* Electric Piano 1 */ + {0x15, 0x6c, {0x00b,6570,100, 0,0,0x00,0x28,0x38,0xf0,0x00,0x0c,0x0}}, + {0x00, 0x7f, {0x06c,6375,100, 0,2,0x00,0xb0,0x22,0xf4,0x23,0x19,0x0}} +}; +static const struct opl4_region regions_05[] = { /* Electric Piano 2 */ + {0x14, 0x27, {0x12c,7476,100, 0,3,0x00,0xa2,0x1b,0xf2,0x13,0x08,0x0}}, + {0x28, 0x2d, {0x12d,6818,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, + {0x2e, 0x33, {0x12e,5901,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, + {0x34, 0x39, {0x12f,5292,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, + {0x3a, 0x3f, {0x130,4262,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, + {0x40, 0x45, {0x131,3627,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, + {0x46, 0x4b, {0x132,3118,100, 0,3,0x04,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, + {0x4c, 0x52, {0x133,2083,100, 0,3,0x03,0xa2,0x1b,0xf2,0x14,0x18,0x0}}, + {0x53, 0x58, {0x134,1446,100, 0,3,0x07,0xa2,0x1b,0xf3,0x14,0x18,0x0}}, + {0x59, 0x6d, {0x135,1917,100, 0,3,0x00,0xa2,0x1b,0xf4,0x15,0x08,0x0}}, + {0x14, 0x2d, {0x12c,7472,100, 0,0,0x00,0xa2,0x18,0xf2,0x13,0x08,0x0}}, + {0x2e, 0x33, {0x12d,6814,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, + {0x34, 0x39, {0x12e,5897,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, + {0x3a, 0x3f, {0x12f,5288,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, + {0x40, 0x45, {0x130,4258,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}}, + {0x46, 0x4b, {0x131,3623,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}}, + {0x4c, 0x52, {0x132,3114,100, 0,0,0x04,0xa2,0x18,0xf2,0x14,0x08,0x0}}, + {0x53, 0x58, {0x133,2079,100, 0,0,0x07,0xa2,0x18,0xf2,0x14,0x18,0x0}}, + {0x59, 0x5e, {0x134,1442,100, 0,0,0x0a,0xa2,0x18,0xf3,0x14,0x18,0x0}}, + {0x5f, 0x6d, {0x135,1913,100, 0,0,0x00,0xa2,0x18,0xf4,0x15,0x08,0x0}} +}; +static const struct opl4_region regions_06[] = { /* Harpsichord */ + {0x15, 0x39, {0x080,5158,100, 0,0,0x00,0xb2,0x20,0xf5,0x24,0x19,0x0}}, + {0x3a, 0x3f, {0x081,4408,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}}, + {0x40, 0x45, {0x082,3622,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}}, + {0x46, 0x4d, {0x083,2843,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x19,0x0}}, + {0x4e, 0x6c, {0x084,1307,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x29,0x0}} +}; +static const struct opl4_region regions_07[] = { /* Clavinet */ + {0x15, 0x51, {0x027,5009,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x2b,0x0}}, + {0x52, 0x6c, {0x028,3495,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x3b,0x0}} +}; +static const struct opl4_region regions_08[] = { /* Celesta */ + {0x15, 0x6c, {0x02b,3267,100, 0,0,0x00,0xdc,0x20,0xf4,0x15,0x07,0x3}} +}; +static const struct opl4_region regions_09[] = { /* Glockenspiel */ + {0x15, 0x78, {0x0f3, 285,100, 0,0,0x00,0xc2,0x28,0xf6,0x25,0x25,0x0}} +}; +static const struct opl4_region regions_0a[] = { /* Music Box */ + {0x15, 0x6c, {0x0f3,3362,100, 0,0,0x00,0xb6,0x20,0xa6,0x25,0x25,0x0}}, + {0x15, 0x6c, {0x101,4773,100, 0,0,0x00,0xaa,0x20,0xd4,0x14,0x16,0x0}} +}; +static const struct opl4_region regions_0b[] = { /* Vibraphone */ + {0x15, 0x6c, {0x101,4778,100, 0,0,0x00,0xc0,0x28,0xf4,0x14,0x16,0x4}} +}; +static const struct opl4_region regions_0c[] = { /* Marimba */ + {0x15, 0x3f, {0x0f4,4778,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}}, + {0x40, 0x4c, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}}, + {0x4d, 0x5a, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x08,0x0}}, + {0x5b, 0x7f, {0x0f5,3218,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x18,0x0}} +}; +static const struct opl4_region regions_0d[] = { /* Xylophone */ + {0x00, 0x7f, {0x136,1729,100, 0,0,0x00,0xd2,0x38,0xf0,0x06,0x36,0x0}} +}; +static const struct opl4_region regions_0e[] = { /* Tubular Bell */ + {0x01, 0x7f, {0x0ff,3999,100, 0,1,0x00,0x90,0x21,0xf4,0xa3,0x25,0x1}} +}; +static const struct opl4_region regions_0f[] = { /* Dulcimer */ + {0x00, 0x7f, {0x03f,4236,100, 0,1,0x00,0xbc,0x29,0xf5,0x16,0x07,0x0}}, + {0x00, 0x7f, {0x040,4236,100, 0,2,0x0e,0x94,0x2a,0xf5,0x16,0x07,0x0}} +}; +static const struct opl4_region regions_10[] = { /* Drawbar Organ */ + {0x01, 0x7f, {0x08e,4394,100, 0,2,0x14,0xc2,0x3a,0xf0,0x00,0x0a,0x0}} +}; +static const struct opl4_region regions_11[] = { /* Percussive Organ */ + {0x15, 0x3b, {0x08c,6062,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}}, + {0x3c, 0x6c, {0x08d,2984,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_12[] = { /* Rock Organ */ + {0x15, 0x30, {0x128,6574,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, + {0x31, 0x3c, {0x129,5040,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, + {0x3d, 0x48, {0x12a,3498,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, + {0x49, 0x54, {0x12b,1957,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, + {0x55, 0x6c, {0x127, 423,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}} +}; +static const struct opl4_region regions_13[] = { /* Church Organ */ + {0x15, 0x29, {0x087,7466,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, + {0x2a, 0x30, {0x088,6456,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, + {0x31, 0x38, {0x089,5428,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, + {0x39, 0x41, {0x08a,4408,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, + {0x42, 0x6c, {0x08b,3406,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_14[] = { /* Reed Organ */ + {0x00, 0x53, {0x0ac,5570,100, 0,0,0x06,0xc0,0x38,0xf0,0x00,0x09,0x1}}, + {0x54, 0x7f, {0x0ad,2497,100, 0,0,0x00,0xc0,0x38,0xf0,0x00,0x09,0x1}} +}; +static const struct opl4_region regions_15[] = { /* Accordion */ + {0x15, 0x4c, {0x006,4261,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}}, + {0x4d, 0x6c, {0x007,1530,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}}, + {0x15, 0x6c, {0x070,4391,100, 0,3,0x00,0x8a,0x23,0xa0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_16[] = { /* Harmonica */ + {0x15, 0x6c, {0x070,4408,100, 0,0,0x00,0xae,0x30,0xa0,0x00,0x09,0x2}} +}; +static const struct opl4_region regions_17[] = { /* Tango Accordion */ + {0x00, 0x53, {0x0ac,5573,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}}, + {0x54, 0x7f, {0x0ad,2500,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}}, + {0x15, 0x6c, {0x041,8479,100, 0,2,0x00,0x6a,0x3a,0x75,0x20,0x0a,0x0}} +}; +static const struct opl4_region regions_18[] = { /* Nylon Guitar */ + {0x15, 0x2f, {0x0b3,6964,100, 0,0,0x05,0xca,0x28,0xf5,0x34,0x09,0x0}}, + {0x30, 0x36, {0x0b7,5567,100, 0,0,0x0c,0xca,0x28,0xf5,0x34,0x09,0x0}}, + {0x37, 0x3c, {0x0b5,4653,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, + {0x3d, 0x43, {0x0b4,3892,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x09,0x0}}, + {0x44, 0x60, {0x0b6,2723,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x19,0x0}} +}; +static const struct opl4_region regions_19[] = { /* Steel Guitar */ + {0x15, 0x31, {0x00c,6937,100, 0,0,0x00,0xbc,0x28,0xf0,0x04,0x19,0x0}}, + {0x32, 0x38, {0x00d,5410,100, 0,0,0x00,0xbc,0x28,0xf0,0x05,0x09,0x0}}, + {0x39, 0x47, {0x00e,4379,100, 0,0,0x00,0xbc,0x28,0xf5,0x94,0x09,0x0}}, + {0x48, 0x6c, {0x00f,2843,100, 0,0,0x00,0xbc,0x28,0xf6,0x95,0x09,0x0}} +}; +static const struct opl4_region regions_1a[] = { /* Jazz Guitar */ + {0x15, 0x31, {0x05a,6832,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, + {0x32, 0x3f, {0x05b,4897,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, + {0x40, 0x6c, {0x05c,3218,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}} +}; +static const struct opl4_region regions_1b[] = { /* Clean Guitar */ + {0x15, 0x2c, {0x061,7053,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}}, + {0x2d, 0x31, {0x060,6434,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}}, + {0x32, 0x38, {0x063,5764,100, 0,1,0x00,0xbe,0x29,0xf5,0x55,0x0a,0x0}}, + {0x39, 0x3f, {0x062,4627,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x0a,0x0}}, + {0x40, 0x44, {0x065,3963,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}}, + {0x45, 0x4b, {0x064,3313,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}}, + {0x4c, 0x54, {0x066,2462,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x2a,0x0}}, + {0x55, 0x6c, {0x067,1307,100, 0,1,0x00,0xb4,0x29,0xf6,0x56,0x0a,0x0}} +}; +static const struct opl4_region regions_1c[] = { /* Muted Guitar */ + {0x01, 0x7f, {0x068,4408,100, 0,0,0x00,0xcc,0x28,0xf6,0x15,0x09,0x0}} +}; +static const struct opl4_region regions_1d[] = { /* Overdriven Guitar */ + {0x00, 0x40, {0x0a5,6589,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}}, + {0x41, 0x7f, {0x0a6,5428,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}} +}; +static const struct opl4_region regions_1e[] = { /* Distortion Guitar */ + {0x15, 0x2a, {0x051,6928,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x2b, 0x2e, {0x052,6433,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x2f, 0x32, {0x053,5944,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x33, 0x36, {0x054,5391,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x37, 0x3a, {0x055,4897,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x3b, 0x3e, {0x056,4408,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x3f, 0x42, {0x057,3892,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x43, 0x46, {0x058,3361,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, + {0x47, 0x6c, {0x059,2784,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}} +}; +static const struct opl4_region regions_1f[] = { /* Guitar Harmonics */ + {0x15, 0x44, {0x05e,5499,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}}, + {0x45, 0x49, {0x05d,4850,100, 0,0,0x00,0xe2,0x28,0xf4,0x24,0x09,0x0}}, + {0x4a, 0x6c, {0x05f,4259,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}} +}; +static const struct opl4_region regions_20[] = { /* Acoustic Bass */ + {0x15, 0x30, {0x004,8053,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}}, + {0x31, 0x6c, {0x005,4754,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}} +}; +static const struct opl4_region regions_21[] = { /* Fingered Bass */ + {0x01, 0x20, {0x04a,8762,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, + {0x21, 0x25, {0x04b,8114,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, + {0x26, 0x2a, {0x04c,7475,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, + {0x2b, 0x7f, {0x04d,6841,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}} +}; +static const struct opl4_region regions_22[] = { /* Picked Bass */ + {0x15, 0x23, {0x04f,7954,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x0a,0x0}}, + {0x24, 0x2a, {0x050,7318,100, 0,0,0x05,0xcc,0x18,0xf3,0x90,0x1a,0x0}}, + {0x2b, 0x2f, {0x06b,6654,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x2a,0x0}}, + {0x30, 0x47, {0x069,6031,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}}, + {0x48, 0x6c, {0x06a,5393,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}} +}; +static const struct opl4_region regions_23[] = { /* Fretless Bass */ + {0x01, 0x7f, {0x04e,5297,100, 0,0,0x00,0xd2,0x10,0xf3,0x63,0x19,0x0}} +}; +static const struct opl4_region regions_24[] = { /* Slap Bass 1 */ + {0x15, 0x6c, {0x0a3,7606,100, 0,1,0x00,0xde,0x19,0xf5,0x32,0x1a,0x0}} +}; +static const struct opl4_region regions_25[] = { /* Slap Bass 2 */ + {0x01, 0x7f, {0x0a2,6694,100, 0,0,0x00,0xda,0x20,0xb0,0x02,0x09,0x0}} +}; +static const struct opl4_region regions_26[] = { /* Synth Bass 1 */ + {0x15, 0x6c, {0x0be,7466,100, 0,1,0x00,0xb8,0x39,0xf4,0x14,0x09,0x0}} +}; +static const struct opl4_region regions_27[] = { /* Synth Bass 2 */ + {0x00, 0x7f, {0x117,8103,100, 0,1,0x00,0xca,0x39,0xf3,0x50,0x08,0x0}} +}; +static const struct opl4_region regions_28[] = { /* Violin */ + {0x15, 0x3a, {0x105,5158,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x3b, 0x3f, {0x102,4754,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x40, 0x41, {0x106,4132,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x42, 0x44, {0x107,4033,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x45, 0x47, {0x108,3580,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x48, 0x4a, {0x10a,2957,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x4b, 0x4c, {0x10b,2724,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x4d, 0x4e, {0x10c,2530,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x4f, 0x51, {0x10d,2166,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, + {0x52, 0x6c, {0x109,1825,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}} +}; +static const struct opl4_region regions_29[] = { /* Viola */ + {0x15, 0x32, {0x103,5780,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, + {0x33, 0x35, {0x104,5534,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, + {0x36, 0x38, {0x105,5158,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, + {0x39, 0x3d, {0x102,4754,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, + {0x3e, 0x3f, {0x106,4132,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, + {0x40, 0x42, {0x107,4033,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, + {0x43, 0x45, {0x108,3580,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, + {0x46, 0x48, {0x10a,2957,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, + {0x49, 0x4a, {0x10b,2724,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, + {0x4b, 0x4c, {0x10c,2530,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, + {0x4d, 0x4f, {0x10d,2166,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, + {0x50, 0x6c, {0x109,1825,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}} +}; +static const struct opl4_region regions_2a[] = { /* Cello */ + {0x15, 0x2d, {0x112,6545,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}}, + {0x2e, 0x37, {0x113,5764,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}}, + {0x38, 0x3e, {0x115,4378,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}, + {0x3f, 0x44, {0x116,3998,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}, + {0x45, 0x6c, {0x114,3218,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}} +}; +static const struct opl4_region regions_2b[] = { /* Contrabass */ + {0x15, 0x29, {0x110,7713,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}}, + {0x2a, 0x6c, {0x111,6162,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_2c[] = { /* Tremolo Strings */ + {0x15, 0x3b, {0x0b0,4810,100, 0,0,0x0a,0xde,0x38,0xf0,0x00,0x07,0x6}}, + {0x3c, 0x41, {0x035,4035,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, + {0x42, 0x47, {0x033,3129,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, + {0x48, 0x52, {0x034,2625,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, + {0x53, 0x6c, {0x0af, 936,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x07,0x6}} +}; +static const struct opl4_region regions_2d[] = { /* Pizzicato Strings */ + {0x15, 0x32, {0x0b8,6186,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, + {0x33, 0x3b, {0x0b9,5031,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, + {0x3c, 0x42, {0x0bb,4146,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, + {0x43, 0x48, {0x0ba,3245,100, 0,0,0x00,0xc2,0x28,0xf0,0x00,0x05,0x0}}, + {0x49, 0x6c, {0x0bc,2352,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}} +}; +static const struct opl4_region regions_2e[] = { /* Harp */ + {0x15, 0x46, {0x07e,3740,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}}, + {0x47, 0x6c, {0x07f,2319,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}} +}; +static const struct opl4_region regions_2f[] = { /* Timpani */ + {0x15, 0x6c, {0x100,6570,100, 0,0,0x00,0xf8,0x28,0xf0,0x05,0x16,0x0}} +}; +static const struct opl4_region regions_30[] = { /* Strings */ + {0x15, 0x3b, {0x13c,4806,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, + {0x3c, 0x41, {0x13e,4035,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, + {0x42, 0x47, {0x13d,3122,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, + {0x48, 0x52, {0x13f,2629,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}}, + {0x53, 0x6c, {0x140, 950,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}} +}; +static const struct opl4_region regions_31[] = { /* Slow Strings */ + {0x15, 0x3b, {0x0b0,4810,100, 0,1,0x0a,0xbe,0x19,0xf0,0x00,0x07,0x0}}, + {0x3c, 0x41, {0x035,4035,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, + {0x42, 0x47, {0x033,3129,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, + {0x48, 0x52, {0x034,2625,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, + {0x53, 0x6c, {0x0af, 936,100, 0,1,0x00,0xbe,0x19,0xf0,0x00,0x07,0x0}} +}; +static const struct opl4_region regions_32[] = { /* Synth Strings 1 */ + {0x05, 0x71, {0x002,6045,100,-2,0,0x00,0xa6,0x20,0x93,0x22,0x06,0x0}}, + {0x15, 0x6c, {0x0ae,3261,100, 2,0,0x00,0xc6,0x20,0x70,0x01,0x06,0x0}} +}; +static const struct opl4_region regions_33[] = { /* Synth Strings 2 */ + {0x15, 0x6c, {0x002,4513,100, 5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}}, + {0x15, 0x6c, {0x002,4501,100,-5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}} +}; +static const struct opl4_region regions_34[] = { /* Choir Aahs */ + {0x15, 0x3a, {0x018,5010,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, + {0x3b, 0x40, {0x019,4370,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, + {0x41, 0x47, {0x01a,3478,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, + {0x48, 0x6c, {0x01b,2197,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}} +}; +static const struct opl4_region regions_35[] = { /* Voice Oohs */ + {0x15, 0x6c, {0x029,3596,100, 0,0,0x00,0xe6,0x20,0xf7,0x20,0x08,0x0}} +}; +static const struct opl4_region regions_36[] = { /* Synth Voice */ + {0x15, 0x6c, {0x02a,3482,100, 0,1,0x00,0xc2,0x19,0x85,0x21,0x07,0x0}} +}; +static const struct opl4_region regions_37[] = { /* Orchestra Hit */ + {0x15, 0x6c, {0x049,4394,100, 0,0,0x00,0xfe,0x30,0x80,0x05,0x05,0x0}} +}; +static const struct opl4_region regions_38[] = { /* Trumpet */ + {0x15, 0x3c, {0x0f6,4706,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, + {0x3d, 0x43, {0x0f8,3894,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, + {0x44, 0x48, {0x0f7,3118,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, + {0x49, 0x4e, {0x0fa,2322,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, + {0x4f, 0x55, {0x0f9,1634,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, + {0x56, 0x6c, {0x0fb, 786,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}} +}; +static const struct opl4_region regions_39[] = { /* Trombone */ + {0x15, 0x3a, {0x0f0,5053,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}, + {0x3b, 0x3f, {0x0f1,4290,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}, + {0x40, 0x6c, {0x0f2,3580,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_3a[] = { /* Tuba */ + {0x15, 0x2d, {0x085,7096,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}}, + {0x2e, 0x6c, {0x086,6014,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}} +}; +static const struct opl4_region regions_3b[] = { /* Muted Trumpet */ + {0x15, 0x45, {0x0b1,4135,100, 0,0,0x00,0xcc,0x28,0xf3,0x10,0x0a,0x1}}, + {0x46, 0x6c, {0x0b2,2599,100, 0,0,0x00,0xcc,0x28,0x83,0x10,0x0a,0x1}} +}; +static const struct opl4_region regions_3c[] = { /* French Horns */ + {0x15, 0x49, {0x07c,3624,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}}, + {0x4a, 0x6c, {0x07d,2664,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_3d[] = { /* Brass Section */ + {0x15, 0x42, {0x0fc,4375,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}}, + {0x43, 0x6c, {0x0fd,2854,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}} +}; +static const struct opl4_region regions_3e[] = { /* Synth Brass 1 */ + {0x01, 0x27, {0x0d3,9094,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x28, 0x2d, {0x0da,8335,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x2e, 0x33, {0x0d4,7558,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x34, 0x39, {0x0db,6785,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x3a, 0x3f, {0x0d5,6042,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x40, 0x45, {0x0dc,5257,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x46, 0x4b, {0x0d6,4493,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x4c, 0x51, {0x0dd,3741,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x52, 0x57, {0x0d7,3012,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x58, 0x5d, {0x0de,2167,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x5e, 0x63, {0x0d8,1421,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x64, 0x7f, {0x0d9,-115,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, + {0x01, 0x27, {0x118,9103,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x28, 0x2d, {0x119,8340,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x2e, 0x33, {0x11a,7565,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x34, 0x39, {0x11b,6804,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x3a, 0x3f, {0x11c,6042,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x40, 0x45, {0x11d,5277,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x46, 0x4b, {0x11e,4520,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x4c, 0x51, {0x11f,3741,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x52, 0x57, {0x120,3012,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x58, 0x5d, {0x121,2166,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x5e, 0x64, {0x122,1421,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, + {0x65, 0x7f, {0x123,-115,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}} +}; +static const struct opl4_region regions_3f[] = { /* Synth Brass 2 */ + {0x01, 0x27, {0x118,9113,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x28, 0x2d, {0x119,8350,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x2e, 0x33, {0x11a,7575,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x34, 0x39, {0x11b,6814,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x3a, 0x3f, {0x11c,6052,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x40, 0x45, {0x11d,5287,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x46, 0x4b, {0x11e,4530,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x4c, 0x51, {0x11f,3751,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x52, 0x57, {0x120,3022,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x58, 0x5d, {0x121,2176,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x5e, 0x64, {0x122,1431,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x65, 0x7f, {0x123,-105,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, + {0x00, 0x7f, {0x124,4034,100,-3,2,0x00,0xea,0x22,0x85,0x23,0x08,0x0}} +}; +static const struct opl4_region regions_40[] = { /* Soprano Sax */ + {0x15, 0x3f, {0x0e3,4228,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}, + {0x40, 0x45, {0x0e4,3495,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}, + {0x46, 0x4b, {0x0e5,2660,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, + {0x4c, 0x51, {0x0e6,2002,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, + {0x52, 0x59, {0x0e7,1186,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, + {0x59, 0x6c, {0x0e8,1730,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}} +}; +static const struct opl4_region regions_41[] = { /* Alto Sax */ + {0x15, 0x32, {0x092,6204,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x33, 0x35, {0x096,5812,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x36, 0x3a, {0x099,5318,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x3b, 0x3b, {0x08f,5076,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x3c, 0x3e, {0x093,4706,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x3f, 0x41, {0x097,4321,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x42, 0x44, {0x09a,3893,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x45, 0x47, {0x090,3497,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x48, 0x4a, {0x094,3119,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x4b, 0x4d, {0x098,2726,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x4e, 0x50, {0x09b,2393,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x51, 0x53, {0x091,2088,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, + {0x54, 0x6c, {0x095,1732,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}} +}; +static const struct opl4_region regions_42[] = { /* Tenor Sax */ + {0x24, 0x30, {0x0e9,6301,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, + {0x31, 0x34, {0x0ea,5781,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, + {0x35, 0x3a, {0x0eb,5053,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, + {0x3b, 0x41, {0x0ed,4165,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, + {0x42, 0x47, {0x0ec,3218,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, + {0x48, 0x51, {0x0ee,2462,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, + {0x52, 0x6c, {0x0ef,1421,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}} +}; +static const struct opl4_region regions_43[] = { /* Baritone Sax */ + {0x15, 0x2d, {0x0df,6714,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, + {0x2e, 0x34, {0x0e1,5552,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, + {0x35, 0x39, {0x0e2,5178,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, + {0x3a, 0x6c, {0x0e0,4437,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}} +}; +static const struct opl4_region regions_44[] = { /* Oboe */ + {0x15, 0x3c, {0x042,4493,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}}, + {0x3d, 0x43, {0x044,3702,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, + {0x44, 0x49, {0x043,2956,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, + {0x4a, 0x4f, {0x046,2166,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, + {0x50, 0x55, {0x045,1420,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, + {0x56, 0x6c, {0x047, 630,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}} +}; +static const struct opl4_region regions_45[] = { /* English Horn */ + {0x15, 0x38, {0x03c,5098,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}, + {0x39, 0x3e, {0x03b,4291,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}, + {0x3f, 0x6c, {0x03d,3540,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_46[] = { /* Bassoon */ + {0x15, 0x22, {0x038,7833,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}, + {0x23, 0x2e, {0x03a,7070,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}, + {0x2f, 0x6c, {0x039,6302,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}} +}; +static const struct opl4_region regions_47[] = { /* Clarinet */ + {0x15, 0x3b, {0x09e,5900,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, + {0x3c, 0x41, {0x0a0,5158,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, + {0x42, 0x4a, {0x09f,4260,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, + {0x4b, 0x6c, {0x0a1,2957,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}} +}; +static const struct opl4_region regions_48[] = { /* Piccolo */ + {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, + {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, + {0x4e, 0x53, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, + {0x54, 0x5f, {0x074,2085,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, + {0x60, 0x6c, {0x075,1421,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}} +}; +static const struct opl4_region regions_49[] = { /* Flute */ + {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}}, + {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}}, + {0x4e, 0x6c, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}} +}; +static const struct opl4_region regions_4a[] = { /* Recorder */ + {0x15, 0x6f, {0x0bd,4897,100, 0,0,0x00,0xec,0x30,0x70,0x00,0x09,0x1}} +}; +static const struct opl4_region regions_4b[] = { /* Pan Flute */ + {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x09,0x3}} +}; +static const struct opl4_region regions_4c[] = { /* Bottle Blow */ + {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xc8,0x38,0xf0,0x00,0x09,0x1}}, + {0x01, 0x7f, {0x125,7372,100, 0,0,0x1e,0x80,0x00,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_4d[] = { /* Shakuhachi */ + {0x00, 0x7f, {0x0ab,4548,100, 0,0,0x00,0xd6,0x30,0xf0,0x00,0x0a,0x3}}, + {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xa2,0x28,0x70,0x00,0x09,0x2}} +}; +static const struct opl4_region regions_4e[] = { /* Whistle */ + {0x00, 0x7f, {0x0aa,1731,100, 0,4,0x00,0xd2,0x2c,0x70,0x00,0x0a,0x0}} +}; +static const struct opl4_region regions_4f[] = { /* Ocarina */ + {0x00, 0x7f, {0x0aa,1731,100, 0,1,0x00,0xce,0x29,0x90,0x00,0x0a,0x1}} +}; +static const struct opl4_region regions_50[] = { /* Square Lead */ + {0x01, 0x2a, {0x0cc,9853,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, + {0x2b, 0x36, {0x0cd,6785,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, + {0x37, 0x42, {0x0ca,5248,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, + {0x43, 0x4e, {0x0cf,3713,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, + {0x4f, 0x5a, {0x0ce,2176,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, + {0x5b, 0x7f, {0x0cb, 640,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, + {0x01, 0x2a, {0x0cc,9844,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, + {0x2b, 0x36, {0x0cd,6776,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, + {0x37, 0x42, {0x0ca,5239,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, + {0x43, 0x4e, {0x0cf,3704,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, + {0x4f, 0x5a, {0x0ce,2167,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, + {0x5b, 0x7f, {0x0cb, 631,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}} +}; +static const struct opl4_region regions_51[] = { /* Sawtooth Lead */ + {0x01, 0x27, {0x118,9108,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x28, 0x2d, {0x119,8345,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x2e, 0x33, {0x11a,7570,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x34, 0x39, {0x11b,6809,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x3a, 0x3f, {0x11c,6047,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x40, 0x45, {0x11d,5282,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x46, 0x4b, {0x11e,4525,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x4c, 0x51, {0x11f,3746,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x52, 0x57, {0x120,3017,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x58, 0x5d, {0x121,2171,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x5e, 0x66, {0x122,1426,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x67, 0x7f, {0x123,-110,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x01, 0x27, {0x118,9098,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x28, 0x2d, {0x119,8335,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x2e, 0x33, {0x11a,7560,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x34, 0x39, {0x11b,6799,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x3a, 0x3f, {0x11c,6037,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x40, 0x45, {0x11d,5272,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x46, 0x4b, {0x11e,4515,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x4c, 0x51, {0x11f,3736,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x52, 0x57, {0x120,3007,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x58, 0x5d, {0x121,2161,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x5e, 0x66, {0x122,1416,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, + {0x67, 0x7f, {0x123,-120,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}} +}; +static const struct opl4_region regions_52[] = { /* Calliope Lead */ + {0x00, 0x7f, {0x0aa,1731,100, 0,0,0x00,0xc2,0x28,0x90,0x00,0x0a,0x2}}, + {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xb6,0x28,0xb0,0x00,0x09,0x2}} +}; +static const struct opl4_region regions_53[] = { /* Chiffer Lead */ + {0x00, 0x7f, {0x13a,3665,100, 0,2,0x00,0xcc,0x2a,0xf0,0x10,0x09,0x1}}, + {0x01, 0x7f, {0x0fe,3660,100, 0,0,0x00,0xbe,0x28,0xf3,0x10,0x17,0x0}} +}; +static const struct opl4_region regions_54[] = { /* Charang Lead */ + {0x00, 0x40, {0x0a5,6594,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}}, + {0x41, 0x7f, {0x0a6,5433,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}}, + {0x01, 0x27, {0x118,9098,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x28, 0x2d, {0x119,8335,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x2e, 0x33, {0x11a,7560,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x34, 0x39, {0x11b,6799,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x3a, 0x3f, {0x11c,6037,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x40, 0x45, {0x11d,5272,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x46, 0x4b, {0x11e,4515,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x4c, 0x51, {0x11f,3736,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x52, 0x57, {0x120,3007,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x58, 0x5d, {0x121,2161,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x5e, 0x66, {0x122,1416,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, + {0x67, 0x7f, {0x123,-120,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}} +}; +static const struct opl4_region regions_55[] = { /* Voice Lead */ + {0x00, 0x7f, {0x0aa,1739,100, 0,6,0x00,0x8c,0x2e,0x90,0x00,0x0a,0x0}}, + {0x15, 0x6c, {0x02a,3474,100, 0,1,0x00,0xd8,0x29,0xf0,0x05,0x0a,0x0}} +}; +static const struct opl4_region regions_56[] = { /* 5ths Lead */ + {0x01, 0x27, {0x118,8468,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x28, 0x2d, {0x119,7705,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x2e, 0x33, {0x11a,6930,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x34, 0x39, {0x11b,6169,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x3a, 0x3f, {0x11c,5407,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x40, 0x45, {0x11d,4642,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x46, 0x4b, {0x11e,3885,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x4c, 0x51, {0x11f,3106,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x52, 0x57, {0x120,2377,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x58, 0x5d, {0x121,1531,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x5e, 0x64, {0x122, 786,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x65, 0x7f, {0x123,-750,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, + {0x05, 0x71, {0x002,4503,100, 0,1,0x00,0xb8,0x31,0xb3,0x20,0x0b,0x0}} +}; +static const struct opl4_region regions_57[] = { /* Bass & Lead */ + {0x00, 0x7f, {0x117,8109,100, 0,1,0x00,0xbc,0x29,0xf3,0x50,0x08,0x0}}, + {0x01, 0x27, {0x118,9097,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x28, 0x2d, {0x119,8334,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x2e, 0x33, {0x11a,7559,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x34, 0x39, {0x11b,6798,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x3a, 0x3f, {0x11c,6036,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x40, 0x45, {0x11d,5271,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x46, 0x4b, {0x11e,4514,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x4c, 0x51, {0x11f,3735,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x52, 0x57, {0x120,3006,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x58, 0x5d, {0x121,2160,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x5e, 0x66, {0x122,1415,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, + {0x67, 0x7f, {0x123,-121,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}} +}; +static const struct opl4_region regions_58[] = { /* New Age Pad */ + {0x15, 0x6c, {0x002,4501,100, 0,4,0x00,0xa4,0x24,0x80,0x01,0x05,0x0}}, + {0x15, 0x6c, {0x0f3,4253,100, 0,3,0x00,0x8c,0x23,0xa2,0x14,0x06,0x1}} +}; +static const struct opl4_region regions_59[] = { /* Warm Pad */ + {0x15, 0x6c, {0x04e,5306,100, 2,2,0x00,0x92,0x2a,0x34,0x23,0x05,0x2}}, + {0x15, 0x6c, {0x029,3575,100,-2,2,0x00,0xbe,0x22,0x31,0x23,0x06,0x0}} +}; +static const struct opl4_region regions_5a[] = { /* Polysynth Pad */ + {0x01, 0x27, {0x118,9111,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x28, 0x2d, {0x119,8348,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x2e, 0x33, {0x11a,7573,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x34, 0x39, {0x11b,6812,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x3a, 0x3f, {0x11c,6050,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x40, 0x45, {0x11d,5285,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x46, 0x4b, {0x11e,4528,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x4c, 0x51, {0x11f,3749,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x52, 0x57, {0x120,3020,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x58, 0x5d, {0x121,2174,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x5e, 0x66, {0x122,1429,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x67, 0x7f, {0x123,-107,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, + {0x00, 0x7f, {0x124,4024,100, 0,2,0x00,0xae,0x22,0xe5,0x20,0x08,0x0}} +}; +static const struct opl4_region regions_5b[] = { /* Choir Pad */ + {0x15, 0x3a, {0x018,5010,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, + {0x3b, 0x40, {0x019,4370,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, + {0x41, 0x47, {0x01a,3478,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, + {0x48, 0x6c, {0x01b,2197,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, + {0x15, 0x6c, {0x02a,3482,100, 0,4,0x00,0x98,0x24,0x65,0x21,0x06,0x0}} +}; +static const struct opl4_region regions_5c[] = { /* Bowed Pad */ + {0x15, 0x6c, {0x101,4790,100,-1,1,0x00,0xbe,0x19,0x44,0x14,0x16,0x0}}, + {0x00, 0x7f, {0x0aa,1720,100, 1,1,0x00,0x94,0x19,0x40,0x00,0x06,0x0}} +}; +static const struct opl4_region regions_5d[] = { /* Metallic Pad */ + {0x15, 0x31, {0x00c,6943,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, + {0x32, 0x38, {0x00d,5416,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, + {0x39, 0x47, {0x00e,4385,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, + {0x48, 0x6c, {0x00f,2849,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, + {0x00, 0x7f, {0x03f,4224,100, 0,1,0x00,0x9c,0x31,0x65,0x16,0x07,0x0}} +}; +static const struct opl4_region regions_5e[] = { /* Halo Pad */ + {0x00, 0x7f, {0x124,4038,100, 0,2,0x00,0xa6,0x1a,0x85,0x23,0x08,0x0}}, + {0x15, 0x6c, {0x02a,3471,100, 0,3,0x00,0xc0,0x1b,0xc0,0x05,0x06,0x0}} +}; +static const struct opl4_region regions_5f[] = { /* Sweep Pad */ + {0x01, 0x27, {0x0d3,9100,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x28, 0x2d, {0x0da,8341,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x2e, 0x33, {0x0d4,7564,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x34, 0x39, {0x0db,6791,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x3a, 0x3f, {0x0d5,6048,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x40, 0x45, {0x0dc,5263,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x46, 0x4b, {0x0d6,4499,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x4c, 0x51, {0x0dd,3747,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x52, 0x57, {0x0d7,3018,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x58, 0x5d, {0x0de,2173,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x5e, 0x63, {0x0d8,1427,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x64, 0x7f, {0x0d9,-109,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, + {0x01, 0x27, {0x0d3,9088,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x28, 0x2d, {0x0da,8329,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x2e, 0x33, {0x0d4,7552,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x34, 0x39, {0x0db,6779,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x3a, 0x3f, {0x0d5,6036,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x40, 0x45, {0x0dc,5251,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x46, 0x4b, {0x0d6,4487,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x4c, 0x51, {0x0dd,3735,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x52, 0x57, {0x0d7,3006,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x58, 0x5d, {0x0de,2161,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x5e, 0x63, {0x0d8,1415,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, + {0x64, 0x7f, {0x0d9,-121,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}} +}; +static const struct opl4_region regions_60[] = { /* Ice Rain */ + {0x01, 0x7f, {0x04e,9345,100, 0,2,0x00,0xcc,0x22,0xa3,0x63,0x17,0x0}}, + {0x00, 0x7f, {0x143,5586, 20, 0,2,0x00,0x6e,0x2a,0xf0,0x05,0x05,0x0}} +}; +static const struct opl4_region regions_61[] = { /* Soundtrack */ + {0x15, 0x6c, {0x002,4501,100, 0,2,0x00,0xb6,0x2a,0x60,0x01,0x05,0x0}}, + {0x15, 0x6c, {0x0f3,1160,100, 0,5,0x00,0xa8,0x2d,0x52,0x14,0x06,0x2}} +}; +static const struct opl4_region regions_62[] = { /* Crystal */ + {0x15, 0x6c, {0x0f3,1826,100, 0,3,0x00,0xb8,0x33,0xf6,0x25,0x25,0x0}}, + {0x15, 0x2c, {0x06d,7454,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}}, + {0x2d, 0x36, {0x06e,5925,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}}, + {0x37, 0x6c, {0x06f,4403,100, 0,3,0x09,0xac,0x3b,0x85,0x24,0x06,0x0}} +}; +static const struct opl4_region regions_63[] = { /* Atmosphere */ + {0x05, 0x71, {0x002,4509,100, 0,2,0x00,0xc8,0x32,0x73,0x22,0x06,0x1}}, + {0x15, 0x2f, {0x0b3,6964,100, 0,2,0x05,0xc2,0x32,0xf5,0x34,0x07,0x2}}, + {0x30, 0x36, {0x0b7,5567,100, 0,2,0x0c,0xc2,0x32,0xf5,0x34,0x07,0x2}}, + {0x37, 0x3c, {0x0b5,4653,100, 0,2,0x00,0xc2,0x32,0xf6,0x34,0x07,0x2}}, + {0x3d, 0x43, {0x0b4,3892,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x07,0x2}}, + {0x44, 0x60, {0x0b6,2723,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x17,0x2}} +}; +static const struct opl4_region regions_64[] = { /* Brightness */ + {0x00, 0x7f, {0x137,5285,100, 0,2,0x00,0xbe,0x2a,0xa5,0x18,0x08,0x0}}, + {0x15, 0x6c, {0x02a,3481,100, 0,1,0x00,0xc8,0x29,0x80,0x05,0x05,0x0}} +}; +static const struct opl4_region regions_65[] = { /* Goblins */ + {0x15, 0x6c, {0x002,4501,100,-1,2,0x00,0xca,0x2a,0x40,0x01,0x05,0x0}}, + {0x15, 0x6c, {0x009,9679, 20, 1,4,0x00,0x3c,0x0c,0x22,0x11,0x06,0x0}} +}; +static const struct opl4_region regions_66[] = { /* Echoes */ + {0x15, 0x6c, {0x02a,3487,100, 0,3,0x00,0xae,0x2b,0xf5,0x21,0x06,0x0}}, + {0x00, 0x7f, {0x124,4027,100, 0,3,0x00,0xae,0x2b,0x85,0x23,0x07,0x0}} +}; +static const struct opl4_region regions_67[] = { /* Sci-Fi */ + {0x15, 0x31, {0x00c,6940,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, + {0x32, 0x38, {0x00d,5413,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, + {0x39, 0x47, {0x00e,4382,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, + {0x48, 0x6c, {0x00f,2846,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, + {0x15, 0x6c, {0x002,4498,100, 0,2,0x00,0xd4,0x22,0x80,0x01,0x05,0x0}} +}; +static const struct opl4_region regions_68[] = { /* Sitar */ + {0x00, 0x7f, {0x10f,4408,100, 0,2,0x00,0xc4,0x32,0xf4,0x15,0x16,0x1}} +}; +static const struct opl4_region regions_69[] = { /* Banjo */ + {0x15, 0x34, {0x013,5685,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, + {0x35, 0x38, {0x014,5009,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, + {0x39, 0x3c, {0x012,4520,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, + {0x3d, 0x44, {0x015,3622,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, + {0x45, 0x4c, {0x017,2661,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, + {0x4d, 0x6d, {0x016,1632,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}} +}; +static const struct opl4_region regions_6a[] = { /* Shamisen */ + {0x15, 0x6c, {0x10e,3273,100, 0,0,0x00,0xc0,0x28,0xf7,0x76,0x08,0x0}} +}; +static const struct opl4_region regions_6b[] = { /* Koto */ + {0x00, 0x7f, {0x0a9,4033,100, 0,0,0x00,0xc6,0x20,0xf0,0x06,0x07,0x0}} +}; +static const struct opl4_region regions_6c[] = { /* Kalimba */ + {0x00, 0x7f, {0x137,3749,100, 0,0,0x00,0xce,0x38,0xf5,0x18,0x08,0x0}} +}; +static const struct opl4_region regions_6d[] = { /* Bagpipe */ + {0x15, 0x39, {0x0a4,7683,100, 0,4,0x00,0xc0,0x1c,0xf0,0x00,0x09,0x0}}, + {0x15, 0x39, {0x0a7,7680,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}}, + {0x3a, 0x6c, {0x0a8,3697,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_6e[] = { /* Fiddle */ + {0x15, 0x3a, {0x105,5158,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x3b, 0x3f, {0x102,4754,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x40, 0x41, {0x106,4132,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x42, 0x44, {0x107,4033,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x45, 0x47, {0x108,3580,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x48, 0x4a, {0x10a,2957,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x4b, 0x4c, {0x10b,2724,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x4d, 0x4e, {0x10c,2530,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x4f, 0x51, {0x10d,2166,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, + {0x52, 0x6c, {0x109,1825,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}} +}; +static const struct opl4_region regions_6f[] = { /* Shanai */ + {0x15, 0x6c, {0x041,6946,100, 0,1,0x00,0xc4,0x31,0x95,0x20,0x09,0x0}} +}; +static const struct opl4_region regions_70[] = { /* Tinkle Bell */ + {0x15, 0x73, {0x0f3,1821,100, 0,3,0x00,0xc8,0x3b,0xd6,0x25,0x25,0x0}}, + {0x00, 0x7f, {0x137,5669,100, 0,3,0x00,0x66,0x3b,0xf5,0x18,0x08,0x0}} +}; +static const struct opl4_region regions_71[] = { /* Agogo */ + {0x15, 0x74, {0x00b,2474,100, 0,0,0x00,0xd2,0x38,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_72[] = { /* Steel Drums */ + {0x01, 0x7f, {0x0fe,3670,100, 0,0,0x00,0xca,0x38,0xf3,0x06,0x17,0x1}}, + {0x15, 0x6c, {0x100,9602,100, 0,0,0x00,0x54,0x38,0xb0,0x05,0x16,0x1}} +}; +static const struct opl4_region regions_73[] = { /* Woodblock */ + {0x15, 0x6c, {0x02c,2963, 50, 0,0,0x07,0xd4,0x00,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_74[] = { /* Taiko Drum */ + {0x13, 0x6c, {0x03e,1194, 50, 0,0,0x00,0xaa,0x38,0xf0,0x04,0x04,0x0}} +}; +static const struct opl4_region regions_75[] = { /* Melodic Tom */ + {0x15, 0x6c, {0x0c7,6418, 50, 0,0,0x00,0xe4,0x38,0xf0,0x05,0x01,0x0}} +}; +static const struct opl4_region regions_76[] = { /* Synth Drum */ + {0x15, 0x6c, {0x026,3898, 50, 0,0,0x00,0xd0,0x38,0xf0,0x04,0x04,0x0}} +}; +static const struct opl4_region regions_77[] = { /* Reverse Cymbal */ + {0x15, 0x6c, {0x031,4138, 50, 0,0,0x00,0xfe,0x38,0x3a,0xf0,0x09,0x0}} +}; +static const struct opl4_region regions_78[] = { /* Guitar Fret Noise */ + {0x15, 0x6c, {0x138,5266,100, 0,0,0x00,0xa0,0x38,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_79[] = { /* Breath Noise */ + {0x01, 0x7f, {0x125,4269,100, 0,0,0x1e,0xd0,0x38,0xf0,0x00,0x09,0x0}} +}; +static const struct opl4_region regions_7a[] = { /* Seashore */ + {0x15, 0x6c, {0x008,2965, 20,-2,0,0x00,0xfe,0x00,0x20,0x03,0x04,0x0}}, + {0x01, 0x7f, {0x037,4394, 20, 2,0,0x14,0xfe,0x00,0x20,0x04,0x05,0x0}} +}; +static const struct opl4_region regions_7b[] = { /* Bird Tweet */ + {0x15, 0x6c, {0x009,8078, 5,-4,7,0x00,0xc2,0x0f,0x22,0x12,0x07,0x0}}, + {0x15, 0x6c, {0x009,3583, 5, 4,5,0x00,0xae,0x15,0x72,0x12,0x07,0x0}} +}; +static const struct opl4_region regions_7c[] = { /* Telephone Ring */ + {0x15, 0x6c, {0x003,3602, 10, 0,0,0x00,0xce,0x00,0xf0,0x00,0x0f,0x0}} +}; +static const struct opl4_region regions_7d[] = { /* Helicopter */ + {0x0c, 0x7f, {0x001,2965, 10,-2,0,0x00,0xe0,0x08,0x30,0x01,0x07,0x0}}, + {0x01, 0x7f, {0x037,4394, 10, 2,0,0x44,0x76,0x00,0x30,0x01,0x07,0x0}} +}; +static const struct opl4_region regions_7e[] = { /* Applause */ + {0x15, 0x6c, {0x036,8273, 20,-6,7,0x00,0xc4,0x0f,0x70,0x01,0x05,0x0}}, + {0x15, 0x6c, {0x036,8115, 5, 6,7,0x00,0xc6,0x07,0x70,0x01,0x05,0x0}} +}; +static const struct opl4_region regions_7f[] = { /* Gun Shot */ + {0x15, 0x6c, {0x139,2858, 20, 0,0,0x00,0xbe,0x38,0xf0,0x03,0x00,0x0}} +}; +static const struct opl4_region regions_drums[] = { + {0x18, 0x18, {0x0cb,6397,100, 3,0,0x00,0xf4,0x38,0xc9,0x1c,0x0c,0x0}}, + {0x19, 0x19, {0x0c4,3714,100, 0,0,0x00,0xe0,0x00,0x97,0x19,0x09,0x0}}, + {0x1a, 0x1a, {0x0c4,3519,100, 0,0,0x00,0xea,0x00,0x61,0x01,0x07,0x0}}, + {0x1b, 0x1b, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0xf7,0x19,0x09,0x0}}, + {0x1c, 0x1c, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0x81,0x01,0x07,0x0}}, + {0x1e, 0x1e, {0x0c3,4783,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x1f, 0x1f, {0x0d1,4042,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, + {0x20, 0x20, {0x0d2,5943,100, 0,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}}, + {0x21, 0x21, {0x011,3842,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}}, + {0x23, 0x23, {0x011,4098,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}}, + {0x24, 0x24, {0x011,4370,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x06,0x0}}, + {0x25, 0x25, {0x0d2,4404,100, 0,0,0x00,0xd6,0x00,0xf0,0x00,0x06,0x0}}, + {0x26, 0x26, {0x0d1,4298,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, + {0x27, 0x27, {0x00a,4403,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, + {0x28, 0x28, {0x0d1,4554,100, 0,0,0x00,0xdc,0x00,0xf0,0x07,0x07,0x0}}, + {0x29, 0x29, {0x0c8,4242,100,-4,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, + {0x2a, 0x2a, {0x079,6160,100, 2,0,0x00,0xe0,0x00,0xf5,0x19,0x09,0x0}}, + {0x2b, 0x2b, {0x0c8,4626,100,-3,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, + {0x2c, 0x2c, {0x07b,6039,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, + {0x2d, 0x2d, {0x0c8,5394,100,-2,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, + {0x2e, 0x2e, {0x07a,5690,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x05,0x0}}, + {0x2f, 0x2f, {0x0c7,5185,100, 2,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, + {0x30, 0x30, {0x0c7,5650,100, 3,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, + {0x31, 0x31, {0x031,4395,100, 2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}}, + {0x32, 0x32, {0x0c7,6162,100, 4,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, + {0x33, 0x33, {0x02e,4391,100,-2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}}, + {0x34, 0x34, {0x07a,3009,100,-2,0,0x00,0xea,0x00,0xf2,0x15,0x05,0x0}}, + {0x35, 0x35, {0x021,4522,100,-3,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, + {0x36, 0x36, {0x025,5163,100, 1,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, + {0x37, 0x37, {0x031,5287,100,-1,0,0x00,0xea,0x00,0xf5,0x16,0x06,0x0}}, + {0x38, 0x38, {0x01d,4395,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, + {0x39, 0x39, {0x031,4647,100,-2,0,0x00,0xea,0x00,0xf4,0x16,0x06,0x0}}, + {0x3a, 0x3a, {0x09d,4426,100,-4,0,0x00,0xe0,0x00,0xf4,0x17,0x07,0x0}}, + {0x3b, 0x3b, {0x02e,4659,100,-2,0,0x00,0xea,0x00,0xf0,0x06,0x06,0x0}}, + {0x3c, 0x3c, {0x01c,4769,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x3d, 0x3d, {0x01c,4611,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x3e, 0x3e, {0x01e,4402,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x3f, 0x3f, {0x01f,4387,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x40, 0x40, {0x01f,3983,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x41, 0x41, {0x09c,4526,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x42, 0x42, {0x09c,4016,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x43, 0x43, {0x00b,4739,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x44, 0x44, {0x00b,4179,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x45, 0x45, {0x02f,4787,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, + {0x46, 0x46, {0x030,4665,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, + {0x47, 0x47, {0x144,4519,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}}, + {0x48, 0x48, {0x144,4111,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}}, + {0x49, 0x49, {0x024,6408,100, 3,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, + {0x4a, 0x4a, {0x024,4144,100, 3,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}}, + {0x4b, 0x4b, {0x020,4001,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, + {0x4c, 0x4c, {0x02c,4402,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x4d, 0x4d, {0x02c,3612,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x4e, 0x4e, {0x022,4129,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x4f, 0x4f, {0x023,4147,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, + {0x50, 0x50, {0x032,4412,100,-4,0,0x00,0xd6,0x00,0xf0,0x08,0x09,0x0}}, + {0x51, 0x51, {0x032,4385,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, + {0x52, 0x52, {0x02f,5935,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}} +}; + +#define REGION(num) { ARRAY_SIZE(regions ## num), regions ## num } +const struct opl4_region_ptr snd_yrw801_regions[0x81] = { + REGION(_00), REGION(_01), REGION(_02), REGION(_03), + REGION(_04), REGION(_05), REGION(_06), REGION(_07), + REGION(_08), REGION(_09), REGION(_0a), REGION(_0b), + REGION(_0c), REGION(_0d), REGION(_0e), REGION(_0f), + REGION(_10), REGION(_11), REGION(_12), REGION(_13), + REGION(_14), REGION(_15), REGION(_16), REGION(_17), + REGION(_18), REGION(_19), REGION(_1a), REGION(_1b), + REGION(_1c), REGION(_1d), REGION(_1e), REGION(_1f), + REGION(_20), REGION(_21), REGION(_22), REGION(_23), + REGION(_24), REGION(_25), REGION(_26), REGION(_27), + REGION(_28), REGION(_29), REGION(_2a), REGION(_2b), + REGION(_2c), REGION(_2d), REGION(_2e), REGION(_2f), + REGION(_30), REGION(_31), REGION(_32), REGION(_33), + REGION(_34), REGION(_35), REGION(_36), REGION(_37), + REGION(_38), REGION(_39), REGION(_3a), REGION(_3b), + REGION(_3c), REGION(_3d), REGION(_3e), REGION(_3f), + REGION(_40), REGION(_41), REGION(_42), REGION(_43), + REGION(_44), REGION(_45), REGION(_46), REGION(_47), + REGION(_48), REGION(_49), REGION(_4a), REGION(_4b), + REGION(_4c), REGION(_4d), REGION(_4e), REGION(_4f), + REGION(_50), REGION(_51), REGION(_52), REGION(_53), + REGION(_54), REGION(_55), REGION(_56), REGION(_57), + REGION(_58), REGION(_59), REGION(_5a), REGION(_5b), + REGION(_5c), REGION(_5d), REGION(_5e), REGION(_5f), + REGION(_60), REGION(_61), REGION(_62), REGION(_63), + REGION(_64), REGION(_65), REGION(_66), REGION(_67), + REGION(_68), REGION(_69), REGION(_6a), REGION(_6b), + REGION(_6c), REGION(_6d), REGION(_6e), REGION(_6f), + REGION(_70), REGION(_71), REGION(_72), REGION(_73), + REGION(_74), REGION(_75), REGION(_76), REGION(_77), + REGION(_78), REGION(_79), REGION(_7a), REGION(_7b), + REGION(_7c), REGION(_7d), REGION(_7e), REGION(_7f), + REGION(_drums) +}; -- cgit v1.3.1