Logo Search packages:      
Sourcecode: alsa-driver version File versions  Download package

gus_simple.c

/*
 *  Routines for Gravis UltraSound soundcards - Simple instrument handlers
 *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it 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 program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

#include <sound/driver.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/gus.h>
#include "gus_tables.h"

/*
 *
 */

static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice);
static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice);
static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice);

static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position);
static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode);
static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq);
static void sample_volume(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume);
static void sample_loop(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop);
static void sample_pos(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_position_t position);
static void sample_private1(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data);

static snd_gus_sample_ops_t sample_ops = {
      sample_start,
      sample_stop,
      sample_freq,
      sample_volume,
      sample_loop,
      sample_pos,
      sample_private1
};

#if 0

static void note_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, int wait);
static void note_wait(snd_gus_card_t *gus, snd_gus_voice_t *voice);
static void note_off(snd_gus_card_t *gus, snd_gus_voice_t *voice);
static void note_volume(snd_gus_card_t *card, snd_gus_voice_t *voice);
static void note_pitchbend(snd_gus_card_t *card, snd_gus_voice_t *voice);
static void note_vibrato(snd_gus_card_t *card, snd_gus_voice_t *voice);
static void note_tremolo(snd_gus_card_t *card, snd_gus_voice_t *voice);

static struct snd_gus_note_handlers note_commands = {
      note_stop,
      note_wait,
      note_off,
      note_volume,
      note_pitchbend,
      note_vibrato,
      note_tremolo
};

static void chn_trigger_down(snd_gus_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority );
static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note );
static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 );

static struct ULTRA_STRU_INSTRUMENT_CHANNEL_COMMANDS channel_commands = {
  chn_trigger_down,
  chn_trigger_up,
  chn_control
};

#endif

static void do_volume_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);
static void do_pan_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);

/*
 *
 */

static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice)
{
      spin_lock(&gus->event_lock);
      snd_gf1_stop_voice(gus, voice->number);
      spin_lock(&gus->reg_lock);
      snd_gf1_select_voice(gus, voice->number);
      snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0);
      spin_unlock(&gus->reg_lock);
      voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;
      spin_unlock(&gus->event_lock);
}

static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice)
{
      spin_lock(&gus->event_lock);
      if (voice->flags & SNDRV_GF1_VFLG_RUNNING)
            do_volume_envelope(gus, voice);
      else
            snd_gf1_stop_voice(gus, voice->number);
      spin_unlock(&gus->event_lock);
}

static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice)
{
      spin_lock(&gus->event_lock);
      if ((voice->flags & (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) ==
                          (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1))
            do_pan_envelope(gus, voice);
      spin_unlock(&gus->event_lock);
}

/*
 *
 */

static void do_volume_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
{
      unsigned short next, rate, old_volume;
      int program_next_ramp;
      unsigned long flags;
  
      if (!gus->gf1.volume_ramp) {
            spin_lock_irqsave(&gus->reg_lock, flags);
            snd_gf1_select_voice(gus, voice->number);
            snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
            snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, voice->gf1_volume);
            /* printk("gf1_volume = 0x%x\n", voice->gf1_volume); */
            spin_unlock_irqrestore(&gus->reg_lock, flags);
            return;
      }
      program_next_ramp = 0;
      rate = next = 0;
      while (1) {
            program_next_ramp = 0;
            rate = next = 0;
            switch (voice->venv_state) {
            case VENV_BEFORE:
                  voice->venv_state = VENV_ATTACK;
                  voice->venv_value_next = 0;
                  spin_lock_irqsave(&gus->reg_lock, flags);
                  snd_gf1_select_voice(gus, voice->number);
                  snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
                  snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME);
                  spin_unlock_irqrestore(&gus->reg_lock, flags);
                  break;
            case VENV_ATTACK:
                  voice->venv_state = VENV_SUSTAIN;
                  program_next_ramp++;
                  next = 255;
                  rate = gus->gf1.volume_ramp;
                  break;
            case VENV_SUSTAIN:
                  voice->venv_state = VENV_RELEASE;
                  spin_lock_irqsave(&gus->reg_lock, flags);
                  snd_gf1_select_voice(gus, voice->number);
                  snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
                  snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, ((int)voice->gf1_volume * (int)voice->venv_value_next) / 255);
                  spin_unlock_irqrestore(&gus->reg_lock, flags);
                  return;
            case VENV_RELEASE:
                  voice->venv_state = VENV_DONE;
                  program_next_ramp++;
                  next = 0;
                  rate = gus->gf1.volume_ramp;
                  break;
            case VENV_DONE:
                  snd_gf1_stop_voice(gus, voice->number);
                  voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;
                  return;
            case VENV_VOLUME:
                  program_next_ramp++;
                  next = voice->venv_value_next;
                  rate = gus->gf1.volume_ramp;
                  voice->venv_state = voice->venv_state_prev;
                  break;
            }
            voice->venv_value_next = next;
            if (!program_next_ramp)
                  continue;
            spin_lock_irqsave(&gus->reg_lock, flags);
            snd_gf1_select_voice(gus, voice->number);
            snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
            old_volume = snd_gf1_read16(gus, SNDRV_GF1_VW_VOLUME) >> 8;
            if (!rate) {
                  spin_unlock_irqrestore(&gus->reg_lock, flags);              
                  continue;
            }
            next = (((int)voice->gf1_volume * (int)next) / 255) >> 8;
            if (old_volume < SNDRV_GF1_MIN_OFFSET)
                  old_volume = SNDRV_GF1_MIN_OFFSET;
            if (next < SNDRV_GF1_MIN_OFFSET)
                  next = SNDRV_GF1_MIN_OFFSET;
            if (next > SNDRV_GF1_MAX_OFFSET)
                  next = SNDRV_GF1_MAX_OFFSET;
            if (old_volume == next) {
                  spin_unlock_irqrestore(&gus->reg_lock, flags);
                  continue;
            }
            voice->volume_control &= ~0xc3;
            voice->volume_control |= 0x20;
            if (old_volume > next) {
                  snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, next);
                  snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, old_volume);
                  voice->volume_control |= 0x40;
            } else {
                  snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, old_volume);
                  snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, next);
            }
            snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, rate);
            snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control);
            if (!gus->gf1.enh_mode) {
                  snd_gf1_delay(gus);
                  snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control);
            }
            spin_unlock_irqrestore(&gus->reg_lock, flags);              
            return;
      }
}

static void do_pan_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
{
      unsigned long flags;
      unsigned char old_pan;

#if 0
      snd_gf1_select_voice(gus, voice->number);
      printk(" -%i- do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n",
            voice->number,
            voice->flags,
            voice->gf1_pan,
            snd_gf1_i_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f);
#endif
      if (gus->gf1.enh_mode) {
            voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN);
            return;
      }
      if (!gus->gf1.smooth_pan) {
            spin_lock_irqsave(&gus->reg_lock, flags);             
            snd_gf1_select_voice(gus, voice->number);
            snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan);
            spin_unlock_irqrestore(&gus->reg_lock, flags);
            return;
      }
      if (!(voice->flags & SNDRV_GF1_VFLG_PAN))       /* before */
            voice->flags |= SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN;
      spin_lock_irqsave(&gus->reg_lock, flags);             
      snd_gf1_select_voice(gus, voice->number);
      old_pan = snd_gf1_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f;
      if (old_pan > voice->gf1_pan )
            old_pan--;
      if (old_pan < voice->gf1_pan)
            old_pan++;
      snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, old_pan);
      spin_unlock_irqrestore(&gus->reg_lock, flags);
      if (old_pan == voice->gf1_pan)                  /* the goal was reached */
            voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN);
#if 0
      snd_gf1_select_voice(gus, voice->number);
      printk(" -%i- (1) do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n",
             voice->number,
             voice->flags,
             voice->gf1_pan,
             snd_gf1_i_read8(gus, GF1_VB_PAN) & 0x0f);
#endif
}

static void set_enhanced_pan(snd_gus_card_t *gus, snd_gus_voice_t *voice, unsigned short pan)
{
      unsigned long flags;
      unsigned short vlo, vro;
  
      vlo = SNDRV_GF1_ATTEN((SNDRV_GF1_ATTEN_TABLE_SIZE-1) - pan);
      vro = SNDRV_GF1_ATTEN(pan);
      if (pan != SNDRV_GF1_ATTEN_TABLE_SIZE - 1 && pan != 0) {
            vlo >>= 1;
            vro >>= 1;
      }
      vlo <<= 4;
      vro <<= 4;
#if 0
      printk("vlo = 0x%x (0x%x), vro = 0x%x (0x%x)\n",
                  vlo, snd_gf1_i_read16(gus, GF1_VW_OFFSET_LEFT),
                  vro, snd_gf1_i_read16(gus, GF1_VW_OFFSET_RIGHT));
#endif
      spin_lock_irqsave(&gus->reg_lock, flags);             
      snd_gf1_select_voice(gus, voice->number);
        snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, vlo);
      snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, vro);
      spin_unlock_irqrestore(&gus->reg_lock, flags);              
      voice->vlo = vlo;
      voice->vro = vro;
}

/*
 *
 */

static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position)
{
      unsigned long flags;
      unsigned int begin, addr, addr_end, addr_start;
      int w_16;
      simple_instrument_t *simple;
      snd_seq_kinstr_t *instr;

      instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);
      if (instr == NULL)
            return;
      voice->instr = instr->instr;  /* copy ID to speedup aliases */
      simple = KINSTR_DATA(instr);
      begin = simple->address.memory << 4;
      w_16 = simple->format & SIMPLE_WAVE_16BIT ? 0x04 : 0;
      addr_start = simple->loop_start;
      if (simple->format & SIMPLE_WAVE_LOOP) {
            addr_end = simple->loop_end;
      } else {
            addr_end = (simple->size << 4) - (w_16 ? 40 : 24);
      }
      if (simple->format & SIMPLE_WAVE_BACKWARD) {
            addr = simple->loop_end;
            if (position < simple->loop_end)
                  addr -= position;
      } else {
            addr = position;
      }
      voice->control = 0x00;
      voice->mode = 0x20;           /* enable offset registers */
      if (simple->format & SIMPLE_WAVE_16BIT)
            voice->control |= 0x04;
      if (simple->format & SIMPLE_WAVE_BACKWARD)
            voice->control |= 0x40;
      if (simple->format & SIMPLE_WAVE_LOOP) {
            voice->control |= 0x08;
      } else {
            voice->control |= 0x20;
      }
      if (simple->format & SIMPLE_WAVE_BIDIR)
            voice->control |= 0x10;
      if (simple->format & SIMPLE_WAVE_ULAW)
            voice->mode |= 0x40;
      if (w_16) {
            addr = ((addr << 1) & ~0x1f) | (addr & 0x0f);
            addr_start = ((addr_start << 1) & ~0x1f) | (addr_start & 0x0f);
            addr_end = ((addr_end << 1) & ~0x1f) | (addr_end & 0x0f);
      }
      addr += begin;
      addr_start += begin;
      addr_end += begin;
      snd_gf1_stop_voice(gus, voice->number);   
      spin_lock_irqsave(&gus->reg_lock, flags);
      snd_gf1_select_voice(gus, voice->number);
      snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo);
      voice->venv_state = VENV_BEFORE;
      voice->volume_control = 0x03;
      snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16);
      snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16);
      snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16);
      if (!gus->gf1.enh_mode) {
            snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan);
      } else {
            snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT, voice->vlo);
            snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, voice->vlo);
            snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT, voice->vro);
            snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, voice->vro);
            snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, voice->effect_accumulator);
            snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, voice->gf1_effect_volume);
            snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, voice->gf1_effect_volume);
      }
      spin_unlock_irqrestore(&gus->reg_lock, flags);
      do_volume_envelope(gus, voice);
      spin_lock_irqsave(&gus->reg_lock, flags);
      snd_gf1_select_voice(gus, voice->number);
      if (gus->gf1.enh_mode)
            snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, voice->mode);
      snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control);
      if (!gus->gf1.enh_mode) {
            snd_gf1_delay(gus);
            snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control );
      }
      spin_unlock_irqrestore(&gus->reg_lock, flags);
#if 0
      snd_gf1_print_voice_registers(gus);
#endif
      voice->flags |= SNDRV_GF1_VFLG_RUNNING;
      snd_seq_instr_free_use(gus->gf1.ilist, instr);
}

static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode)
{
      unsigned char control;
      unsigned long flags;

      if (!(voice->flags & SNDRV_GF1_VFLG_RUNNING))
            return;
      switch (mode) {
      default:
            if (gus->gf1.volume_ramp > 0) {
                  if (voice->venv_state < VENV_RELEASE) {
                        voice->venv_state = VENV_RELEASE;
                        do_volume_envelope(gus, voice);
                  }
            }
            if (mode != SAMPLE_STOP_VENVELOPE) {
                  snd_gf1_stop_voice(gus, voice->number);
                  spin_lock_irqsave(&gus->reg_lock, flags);
                  snd_gf1_select_voice(gus, voice->number);
                  snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME);
                  spin_unlock_irqrestore(&gus->reg_lock, flags);
                  voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;
            }
            break;
      case SAMPLE_STOP_LOOP:        /* disable loop only */
            spin_lock_irqsave(&gus->reg_lock, flags);
            snd_gf1_select_voice(gus, voice->number);
            control = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
            control &= ~(0x83 | 0x04);
            control |= 0x20;
            snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, control);
            spin_unlock_irqrestore(&gus->reg_lock, flags);
            break;
      }
}

static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq)
{
      unsigned long flags;

      spin_lock_irqsave(&gus->reg_lock, flags);
      voice->fc_register = snd_gf1_translate_freq(gus, freq);
      snd_gf1_select_voice(gus, voice->number);
      snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo);
      spin_unlock_irqrestore(&gus->reg_lock, flags);
}

static void sample_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume)
{
      if (volume->volume >= 0) {
            volume->volume &= 0x3fff;
            voice->gf1_volume = snd_gf1_lvol_to_gvol_raw(volume->volume << 2) << 4;
            voice->venv_state_prev = VENV_SUSTAIN;
            voice->venv_state = VENV_VOLUME;
            do_volume_envelope(gus, voice);
        }
      if (volume->lr >= 0) {
            volume->lr &= 0x3fff;
            if (!gus->gf1.enh_mode) {
                  voice->gf1_pan = (volume->lr >> 10) & 15;
                  if (!gus->gf1.full_range_pan) {
                        if (voice->gf1_pan == 0)
                              voice->gf1_pan++;
                        if (voice->gf1_pan == 15)
                              voice->gf1_pan--;
                  }
                  voice->flags &= ~SNDRV_GF1_VFLG_PAN;      /* before */
                  do_pan_envelope(gus, voice);
            } else {
                  set_enhanced_pan(gus, voice, volume->lr >> 7);
            }
      }
}

static void sample_loop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop)
{
      unsigned long flags;
      int w_16 = voice->control & 0x04;
      unsigned int begin, addr_start, addr_end;
      simple_instrument_t *simple;
      snd_seq_kinstr_t *instr;

#if 0
      printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end);
#endif
      instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);
      if (instr == NULL)
            return;
      voice->instr = instr->instr;  /* copy ID to speedup aliases */
      simple = KINSTR_DATA(instr);
      begin = simple->address.memory;
      addr_start = loop->start;
      addr_end = loop->end;
      addr_start = (((addr_start << 1) & ~0x1f) | (addr_start & 0x0f)) + begin;
      addr_end = (((addr_end << 1) & ~0x1f) | (addr_end & 0x0f)) + begin;
      spin_lock_irqsave(&gus->reg_lock, flags);
      snd_gf1_select_voice(gus, voice->number);
      snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16);
      snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16);
      spin_unlock_irqrestore(&gus->reg_lock, flags);
      snd_seq_instr_free_use(gus->gf1.ilist, instr);
}

static void sample_pos(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position)
{
      unsigned long flags;
      int w_16 = voice->control & 0x04;
      unsigned int begin, addr;
      simple_instrument_t *simple;
      snd_seq_kinstr_t *instr;

#if 0
      printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end);
#endif
      instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);
      if (instr == NULL)
            return;
      voice->instr = instr->instr;  /* copy ID to speedup aliases */
      simple = KINSTR_DATA(instr);
      begin = simple->address.memory;
      addr = (((position << 1) & ~0x1f) | (position & 0x0f)) + begin;
      spin_lock_irqsave(&gus->reg_lock, flags);
      snd_gf1_select_voice(gus, voice->number);
      snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16);
      spin_unlock_irqrestore(&gus->reg_lock, flags);
      snd_seq_instr_free_use(gus->gf1.ilist, instr);
}

#if 0

static unsigned char get_effects_mask( ultra_card_t *card, int value )
{
  if ( value > 7 ) return 0;
  if ( card -> gf1.effects && card -> gf1.effects -> chip_type == ULTRA_EFFECT_CHIP_INTERWAVE )
    return card -> gf1.effects -> chip.interwave.voice_output[ value ];
  return 0;
}

#endif

static void sample_private1(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data)
{
#if 0
  unsigned long flags;
  unsigned char uc;

  switch ( *data ) {
    case ULTRA_PRIV1_IW_EFFECT:
      uc = get_effects_mask( card, ultra_get_byte( data, 4 ) );
      uc |= get_effects_mask( card, ultra_get_byte( data, 4 ) >> 4 );
      uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) );
      uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) >> 4 );
      voice -> data.simple.effect_accumulator = uc;
      voice -> data.simple.effect_volume = ultra_translate_voice_volume( card, ultra_get_word( data, 2 ) ) << 4;
      if ( !card -> gf1.enh_mode ) return;
      if ( voice -> flags & VFLG_WAIT_FOR_START ) return;
      if ( voice -> flags & VFLG_RUNNING )
        {
          CLI( &flags );
          gf1_select_voice( card, voice -> number );
          ultra_write8( card, GF1_VB_ACCUMULATOR, voice -> data.simple.effect_accumulator );
          ultra_write16( card, GF1_VW_EFFECT_VOLUME_FINAL, voice -> data.simple.effect_volume );
          STI( &flags );
        }
      break;
   case ULTRA_PRIV1_IW_LFO:
     ultra_lfo_command( card, voice -> number, data );
  }
#endif
}

#if 0

/*
 *
 */

static void note_stop( ultra_card_t *card, ultra_voice_t *voice, int wait )
{
}

static void note_wait( ultra_card_t *card, ultra_voice_t *voice )
{
}

static void note_off( ultra_card_t *card, ultra_voice_t *voice )
{
}

static void note_volume( ultra_card_t *card, ultra_voice_t *voice )
{
}

static void note_pitchbend( ultra_card_t *card, ultra_voice_t *voice )
{
}

static void note_vibrato( ultra_card_t *card, ultra_voice_t *voice )
{
}

static void note_tremolo( ultra_card_t *card, ultra_voice_t *voice )
{
}

/*
 *
 */
 
static void chn_trigger_down( ultra_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority )
{
}

static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note )
{
}

static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 )
{
}

/*
 *
 */
 
#endif

void snd_gf1_simple_init(snd_gus_voice_t *voice)
{
      voice->handler_wave = interrupt_wave;
      voice->handler_volume = interrupt_volume;
      voice->handler_effect = interrupt_effect;
      voice->volume_change = NULL;
      voice->sample_ops = &sample_ops;
}

Generated by  Doxygen 1.6.0   Back to index