コード例 #1
0
static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume)
{
    genmidi_voice_t *opl_voice;
    unsigned int midi_volume;
    unsigned int full_volume;
    unsigned int car_volume;
    unsigned int mod_volume;

    voice->note_volume = volume;

    opl_voice = &voice->current_instr->voices[voice->current_instr_voice];

    // Multiply note volume and channel volume to get the actual volume.

    midi_volume = 2 * (volume_mapping_table[(voice->channel->volume
                  * current_music_volume) / 127] + 1);

    full_volume = (volume_mapping_table[voice->note_volume] * midi_volume)
                >> 9;

    // The volume value to use in the register:
    car_volume = 0x3f - full_volume;

    // Update the volume register(s) if necessary.

    if (car_volume != voice->reg_volume)
    {
        voice->reg_volume = car_volume | (opl_voice->carrier.scale & 0xc0);

        OPL_WriteRegister((OPL_REGS_LEVEL + voice->op2) | voice->array,
                          voice->reg_volume);

        // If we are using non-modulated feedback mode, we must set the
        // volume for both voices.

        if ((opl_voice->feedback & 0x01) != 0
         && opl_voice->modulator.level != 0x3f)
        {
            mod_volume = 0x3f - opl_voice->modulator.level;
            if (mod_volume >= car_volume)
            {
                mod_volume = car_volume;
            }
            OPL_WriteRegister((OPL_REGS_LEVEL + voice->op1) | voice->array,
                              mod_volume |
                              (opl_voice->modulator.scale & 0xc0));
        }
    }
}
コード例 #2
0
ファイル: i_oplmusic.c プロジェクト: tm512/Mint-Doom
static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume)
{
    genmidi_voice_t *opl_voice;
    unsigned int full_volume;
    unsigned int op_volume;
    unsigned int reg_volume;

    voice->note_volume = volume;

    opl_voice = &voice->current_instr->voices[voice->current_instr_voice];

    // Multiply note volume and channel volume to get the actual volume.

    full_volume = (volume_mapping_table[voice->note_volume]
                   * volume_mapping_table[voice->channel->volume]
                   * volume_mapping_table[current_music_volume]) / (127 * 127);

    // The volume of each instrument can be controlled via GENMIDI:

    op_volume = 0x3f - opl_voice->carrier.level;

    // The volume value to use in the register:

    reg_volume = (op_volume * full_volume) / 128;
    reg_volume = (0x3f - reg_volume) | opl_voice->carrier.scale;

    // Update the volume register(s) if necessary.

    if (reg_volume != voice->reg_volume)
    {
        voice->reg_volume = reg_volume;

        OPL_WriteRegister(OPL_REGS_LEVEL + voice->op2, reg_volume);

        // If we are using non-modulated feedback mode, we must set the
        // volume for both voices.
        // Note that the same register volume value is written for
        // both voices, always calculated from the carrier's level
        // value.

        if ((opl_voice->feedback & 0x01) != 0)
        {
            OPL_WriteRegister(OPL_REGS_LEVEL + voice->op1, reg_volume);
        }
    }
}
コード例 #3
0
static void SetVoicePan(opl_voice_t *voice, unsigned int pan)
{
    genmidi_voice_t *opl_voice;

    voice->reg_pan = pan;
    opl_voice = &voice->current_instr->voices[voice->current_instr_voice];;

    OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array,
                      opl_voice->feedback | pan);
}
コード例 #4
0
ファイル: i_oplmusic.c プロジェクト: tm512/Mint-Doom
static void LoadOperatorData(int operator, genmidi_op_t *data,
                             boolean max_level)
{
    int level;

    // The scale and level fields must be combined for the level register.
    // For the carrier wave we always set the maximum level.

    level = (data->scale & 0xc0) | (data->level & 0x3f);

    if (max_level)
    {
        level |= 0x3f;
    }

    OPL_WriteRegister(OPL_REGS_LEVEL + operator, level);
    OPL_WriteRegister(OPL_REGS_TREMOLO + operator, data->tremolo);
    OPL_WriteRegister(OPL_REGS_ATTACK + operator, data->attack);
    OPL_WriteRegister(OPL_REGS_SUSTAIN + operator, data->sustain);
    OPL_WriteRegister(OPL_REGS_WAVEFORM + operator, data->waveform);
}
コード例 #5
0
static void SetVoiceInstrument(opl_voice_t *voice,
                               genmidi_instr_t *instr,
                               unsigned int instr_voice)
{
    genmidi_voice_t *data;
    unsigned int modulating;

    // Instrument already set for this channel?

    if (voice->current_instr == instr
     && voice->current_instr_voice == instr_voice)
    {
        return;
    }

    voice->current_instr = instr;
    voice->current_instr_voice = instr_voice;

    data = &instr->voices[instr_voice];

    // Are we usind modulated feedback mode?

    modulating = (data->feedback & 0x01) == 0;

    // Doom loads the second operator first, then the first.
    // The carrier is set to minimum volume until the voice volume
    // is set in SetVoiceVolume (below).  If we are not using
    // modulating mode, we must set both to minimum volume.

    LoadOperatorData(voice->op2 | voice->array, &data->carrier, true);
    LoadOperatorData(voice->op1 | voice->array, &data->modulator, !modulating);

    // Set feedback register that control the connection between the
    // two operators.  Turn on bits in the upper nybble; I think this
    // is for OPL3, where it turns on channel A/B.

    OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array,
                      data->feedback | voice->reg_pan);

    // Hack to force a volume update.

    voice->reg_volume = 999;

    // Calculate voice priority.

    voice->priority = 0x0f - (data->carrier.attack >> 4)
                    + 0x0f - (data->carrier.sustain & 0x0f);
}
コード例 #6
0
ファイル: opl.c プロジェクト: Garcia98/prboom3ds
void OPL_InitRegisters(void)
{
	int r;

	// Initialize level registers

	for (r = OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r)
	{
		OPL_WriteRegister(r, 0x3f);
	}

	// Initialize other registers
	// These two loops write to registers that actually don't exist,
	// but this is what Doom does ...
	// Similarly, the <= is also intenational.

	for (r = OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r)
	{
		OPL_WriteRegister(r, 0x00);
	}

	// More registers ...

	for (r = 1; r < OPL_REGS_LEVEL; ++r)
	{
		OPL_WriteRegister(r, 0x00);
	}

	// Re-initialize the low registers:

	// Reset both timers and enable interrupts:
	OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60);
	OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80);

	// "Allow FM chips to control the waveform of each operator":
	OPL_WriteRegister(OPL_REG_WAVEFORM_ENABLE, 0x20);

	// Keyboard split point on (?)
	OPL_WriteRegister(OPL_REG_FM_MODE, 0x40);
}
コード例 #7
0
ファイル: opl.c プロジェクト: DooMJunkie/wii-doom-1
int OPL_Detect(void)
{
    int result1, result2;
    int i;

    // Reset both timers:
    OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60);

    // Enable interrupts:
    OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80);

    // Read status
    result1 = OPL_ReadStatus();

    // Set timer:
    OPL_WriteRegister(OPL_REG_TIMER1, 0xff);

    // Start timer 1:
    OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x21);

    // Wait for 80 microseconds
    // This is how Doom does it:

    for (i=0; i<200; ++i)
    {
        OPL_ReadStatus();
    }

    OPL_Delay(1 * OPL_MS);

    // Read status
    result2 = OPL_ReadStatus();

    // Reset both timers:
    OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60);

    // Enable interrupts:
    OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80);

    return (result1 & 0xe0) == 0x00
        && (result2 & 0xe0) == 0xc0;
}