sound/drivers/opl4/opl4_synth.c
Source file repositories/reference/linux-study-clean/sound/drivers/opl4/opl4_synth.c
File Facts
- System
- Linux kernel
- Corpus path
sound/drivers/opl4/opl4_synth.c- Extension
.c- Size
- 22897 bytes
- Lines
- 621
- Domain
- Driver Families
- Bucket
- sound/drivers
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
opl4_local.hlinux/delay.hlinux/io.hsound/asoundef.h
Detected Declarations
function snd_opl4_synth_resetfunction scoped_guardfunction snd_opl4_synth_shutdownfunction snd_opl4_do_for_notefunction snd_opl4_do_for_channelfunction snd_opl4_do_for_allfunction snd_opl4_update_volumefunction snd_opl4_update_panfunction snd_opl4_update_vibrato_depthfunction snd_opl4_update_pitchfunction snd_opl4_update_tone_parametersfunction snd_opl4_wait_for_wave_headersfunction snd_opl4_note_onfunction snd_opl4_voice_offfunction snd_opl4_note_offfunction snd_opl4_terminate_voicefunction snd_opl4_terminate_notefunction snd_opl4_controlfunction snd_opl4_sysex
Annotated Snippet
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);
Annotation
- Immediate include surface: `opl4_local.h`, `linux/delay.h`, `linux/io.h`, `sound/asoundef.h`.
- Detected declarations: `function snd_opl4_synth_reset`, `function scoped_guard`, `function snd_opl4_synth_shutdown`, `function snd_opl4_do_for_note`, `function snd_opl4_do_for_channel`, `function snd_opl4_do_for_all`, `function snd_opl4_update_volume`, `function snd_opl4_update_pan`, `function snd_opl4_update_vibrato_depth`, `function snd_opl4_update_pitch`.
- Atlas domain: Driver Families / sound/drivers.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.