diff options
-rw-r--r-- | imuse.cpp | 2647 |
1 files changed, 0 insertions, 2647 deletions
diff --git a/imuse.cpp b/imuse.cpp deleted file mode 100644 index 8428072e7c..0000000000 --- a/imuse.cpp +++ /dev/null @@ -1,2647 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2001 The ScummVM project - * - * 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. - * - * $Header$ - */ - -/* - * Timidity support by Lionel Ulmer <lionel.ulmer@free.fr> - */ - -#include "stdafx.h" -#include "scumm.h" -#include "sound.h" - -#ifdef USE_TIMIDITY -#include <sys/time.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* Copy-pasted from Timidity */ -#define SEQ_MIDIPUTC 5 - -#endif /* USE_TIMIDITY */ - -#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) - -#define TICKS_PER_BEAT 480 -#define TEMPO_BASE 0x400000 -#define HARDWARE_TYPE 5 -#define SYSEX_ID 0x7D -#define SPECIAL_CHANNEL 9 - -#define TRIGGER_ID 0 -#define COMMAND_ID 1 - -#ifdef SAMNMAX -#define MDHD_TAG "MDpg" -#else -#define MDHD_TAG "MDhd" -#endif - -static int clamp(int val, int min, int max) { - if (val<min) - return min; - if (val>max) - return max; - return val; -} - -static int transpose_clamp(int a, int b, int c) { - if (b>a) a += (b - a + 11) / 12 * 12; - if (c<a) a -= (a - c + 11) / 12 * 12; - return a; -} - -uint32 get_delta_time(byte **s) { - byte *d = *s,b; - uint32 time = 0; - do { - b = *d++; - time = (time<<7) | (b&0x7F); - } while (b&0x80); - *s = d; - return time; -} - -uint read_word(byte *a) { - return (a[0]<<8) + a[1]; -} - -void skip_midi_cmd(byte **song_ptr) { - byte *s, code; - - const byte num_skip[] = { - 2,2,2,2,1,1,2 - }; - - s = *song_ptr; - - code = *s++; - - if (code<0x80) { - s = NULL; - } else if (code<0xF0) { - s += num_skip[(code&0x70)>>4]; - } else { - if (code==0xF0 || code==0xF7 || code==0xFF && *s++ != 0x2F) { - s += get_delta_time(&s); - } else { - s = NULL; - } - } - *song_ptr = s; -} - -int is_note_cmd(byte **a, IsNoteCmdData *isnote) { - byte *s = *a; - byte code; - - code = *s++; - - switch(code>>4) { - case 8: /* key off */ - isnote->chan = code&0xF; - isnote->note = *s++; - isnote->vel = *s++; - *a = s; - return 1; - case 9: /* key on */ - isnote->chan = code&0xF; - isnote->note = *s++; - isnote->vel = *s++; - *a = s; - if (isnote->vel) - return 2; - return 1; - case 0xA: - case 0xB: - case 0xE: - s++; - case 0xC: - case 0xD: - s++; - break; - case 0xF: - if (code==0xF0 || code==0xF7 || code==0xFF && *s++ != 0x2F) { - s += get_delta_time(&s); - break; - } - return -1; - default: - return -1; - } - *a = s; - return 0; -} - -/**********************************************************************/ - -byte *SoundEngine::findTag(int sound, char *tag, int index) { - byte *ptr = _base_sounds[sound]; - int32 size,pos; - - if (ptr==NULL) { - debug(1, "SoundEngine::findTag completely failed finding sound %d", sound); - return 0; - } - - ptr += 8; - size = READ_BE_UINT32_UNALIGNED(ptr); - ptr += 4; - - pos = 0; - while (pos < size) { - if (!memcmp(ptr + pos, tag, 4) && !index--) - return ptr + pos + 8; - pos += READ_BE_UINT32_UNALIGNED(ptr + pos + 4) + 8; - } - debug(1, "SoundEngine::findTag failed finding sound %d", sound); - return NULL; - -} - -bool SoundEngine::start_sound(int sound) { - Player *player; - void *mdhd; - - mdhd = findTag(sound, MDHD_TAG, 0); - if (!mdhd) - return false; - - player = allocate_player(128); - if (!player) - return false; - - player->clear(); - return player->start_sound(sound); -} - - -Player *SoundEngine::allocate_player(byte priority) { - Player *player = _players, *best = NULL; - int i; - byte bestpri = 255; - - for (i=ARRAYSIZE(_players); i!=0; i--, player++) { - if (!player->_active) - return player; - if (player->_priority < bestpri) { - best = player; - bestpri = player->_priority; - } - } - - if (bestpri < priority) - return best; - - debug(1, "Denying player request"); - return NULL; -} - -void SoundEngine::init_players() { - Player *player = _players; - int i; - - for (i=ARRAYSIZE(_players); i!=0; i--, player++) { - player->_active = false; - player->_se = this; - } -} - -void SoundEngine::init_sustaining_notes() { - SustainingNotes *next = NULL, *sn = _sustaining_notes; - int i; - - _sustain_notes_used = NULL; - _sustain_notes_head = NULL; - - for (i=ARRAYSIZE(_sustaining_notes);i!=0; i--,sn++) { - sn->next = next; - next = sn; - } - _sustain_notes_free = next; -} - -void SoundEngine::init_volume_fader() { - VolumeFader *vf = _volume_fader; - int i; - - for (i=ARRAYSIZE(_volume_fader); i!=0; i--, vf++) - vf->initialize(); - - _active_volume_faders = false; -} - -void SoundEngine::init_parts() { - Part *part; - int i; - MidiChannel *mc; - - for (i=ARRAYSIZE(_parts),part=_parts; i!=0; i--, part++) - part->init(this); - - for(i=0,mc=_midi_channels; i!=ARRAYSIZE(_midi_channels);i++,mc++) - mc->init(i); -} - -int SoundEngine::stop_sound(int sound) { - Player *player = _players; - int i; - int r = -1; - - for (i=ARRAYSIZE(_players); i!=0; i--,player++) { - if (player->_active && player->_id==sound) { - player->clear(); - r = 0; - } - } - return r; -} - -int SoundEngine::stop_all_sounds() { - Player *player = _players; - int i; - - for (i=ARRAYSIZE(_players); i!=0; i--,player++) { - if (player->_active) - player->clear(); - } - return 0; -} - -void SoundEngine::on_timer() { - if (_locked || _paused) - return; - lock(); - sequencer_timers(); - expire_sustain_notes(); - expire_volume_faders(); - unlock(); -} - -void SoundEngine::sequencer_timers() { - Player *player = _players; - int i; - - for (i=ARRAYSIZE(_players); i!=0; i--,player++) { - if (player->_active) - player->sequencer_timer(); - } -} - -void Player::sequencer_timer() { - byte *mtrk; - uint32 counter; - byte *song_ptr; - - counter = _timer_counter + _timer_speed; - _timer_counter = counter&0xFFFF; - _cur_pos += counter>>16; - _tick_index += counter>>16; - - if (_tick_index>=_ticks_per_beat) { - _beat_index += _tick_index/_ticks_per_beat; - _tick_index %= _ticks_per_beat; - } - if (_loop_counter && _beat_index >= _loop_from_beat && _tick_index >= _loop_from_tick) { - _loop_counter--; - jump(_track_index, _loop_to_beat, _loop_to_tick); - } - if (_next_pos <= _cur_pos) { - mtrk = _se->findTag(_song_index, "MTrk", _track_index); - if (!mtrk) { - warning("Sound %d was unloaded while active", _song_index); - clear(); - } else { - song_ptr = mtrk + _song_offset; - _abort = false; - - while (_next_pos <= _cur_pos) { - song_ptr = parse_midi(song_ptr); - if (!song_ptr || _abort) - return; - _next_pos += get_delta_time(&song_ptr); - } - _song_offset = song_ptr - mtrk; - } - } -} - -void SoundEngine::handle_marker(uint id, byte data) { - uint16 *p; - uint pos; - int a; - - pos = _queue_end; - if (pos == _queue_pos) - return; - - if (_queue_adding && _queue_sound==id && data==_queue_marker) - return; - - p = _cmd_queue[pos].array; - - if (p[0] != TRIGGER_ID || p[1] != id || p[2] != data) - return; - - _trigger_count--; - _queue_cleared = false; - do { - pos = (++pos) & (ARRAYSIZE(_cmd_queue)-1); - if (_queue_pos == pos) - break; - p = _cmd_queue[pos].array; - if (*p++ != COMMAND_ID) - break; - _queue_end = pos; - - do_command(p[0],p[1],p[2],p[3],p[4],p[5],p[6],0); - - if (_queue_cleared) - return; - pos = _queue_end; - } while (1); - - _queue_end = pos; -} - -int SoundEngine::get_channel_volume(uint a) { - if (a<8) - return _channel_volume_eff[a]; - return _master_volume; -} - -Part *SoundEngine::allocate_part(byte pri) { - Part *part,*best=NULL; - int i; - - for (i=ARRAYSIZE(_parts),part=_parts; i!=0; i--,part++) { - if (!part->_player) - return part; - if (pri >= part->_pri_eff) { - pri = part->_pri_eff; - best = part; - } - } - - if (best) - best->uninit(); - else - debug(1, "Denying part request"); - return best; -} - -void SoundEngine::expire_sustain_notes() { - SustainingNotes *sn,*next; - Player *player; - uint32 counter; - - for(sn=_sustain_notes_head; sn; sn = next) { - next = sn->next; - player = sn->player; - - counter = sn->counter + player->_timer_speed; - sn->pos += counter>>16; - sn->counter = counter & 0xFFFF; - - if (sn->pos >= sn->off_pos) { - player->key_off(sn->chan, sn->note); - - /* Unlink the node */ - if (next) - next->prev = sn->prev; - if (sn->prev) - sn->prev->next = next; - else - _sustain_notes_head = next; - - /* And put it in the free list */ - sn->next = _sustain_notes_free; - _sustain_notes_free = sn; - } - } -} - -void SoundEngine::expire_volume_faders() { - VolumeFader *vf; - int i; - - if (++_volume_fader_counter & 7) - return; - - if (!_active_volume_faders) - return; - - _active_volume_faders = false; - vf = _volume_fader; - for (i=ARRAYSIZE(_volume_fader); i!=0; i--,vf++) { - if (vf->active) { - _active_volume_faders = true; - vf->on_timer(); - } - } -} - -void VolumeFader::on_timer() { - byte newvol; - - newvol = curvol + speed_hi; - speed_lo_counter += speed_lo; - - if (speed_lo_counter >= speed_lo_max) { - speed_lo_counter -= speed_lo_max; - newvol += direction; - } - - if (curvol!=newvol) { - if (!newvol) { - player->clear(); - active = false; - return; - } - curvol = newvol; - player->set_vol(newvol); - } - - if (!--num_steps) { - active = false; - } -} - -int SoundEngine::get_sound_status(int sound) { - int i; - Player *player; - - for (i=ARRAYSIZE(_players),player=_players; i!=0; i--,player++) { - if (player->_active && player->_id==(uint16)sound) - return 1; - } - return get_queue_sound_status(sound); -} - -int SoundEngine::get_queue_sound_status(int sound) { - uint16 *a; - int i,j; - - j = _queue_pos; - i = _queue_end; - - while (i!=j) { - a = _cmd_queue[i].array; - if (a[0] == COMMAND_ID && a[1] == 8 && a[2] == (uint16)sound) - return 2; - i = (++i) & (ARRAYSIZE(_cmd_queue)-1); - } - return 0; -} - -int SoundEngine::set_volchan(int sound, int volchan) { - int r; - int i; - int num; - Player *player,*best,*sameid; - - r = get_volchan_entry(volchan); - if (r==-1) - return -1; - - if (r >= 8) { - for(i=ARRAYSIZE(_players),player=_players; i!=0; i--,player++) { - if (player->_active && player->_id==(uint16)sound && player->_vol_chan!=(uint16)volchan) { - player->_vol_chan = volchan; - player->set_vol(player->_volume); - return 0; - } - } - return -1; - } else { - best = NULL; - num = 0; - sameid = NULL; - for(i=ARRAYSIZE(_players),player=_players; i!=0; i--,player++) { - if (player->_active) { - if (player->_vol_chan==(uint16)volchan) { - num++; - if (!best || player->_priority <= best->_priority) - best = player; - } else if (player->_id == (uint16)sound) { - sameid = player; - } - } - } - if (sameid==NULL) - return -1; - if (num >= r) - best->clear(); - player->_vol_chan = volchan; - player->set_vol(player->_volume); - return 0; - } -} - -int SoundEngine::clear_queue() { - _queue_adding = false; - _queue_cleared = true; - _queue_pos = 0; - _queue_end = 0; - _trigger_count = 0; - return 0; -} - -int SoundEngine::enqueue_command(int a, int b, int c, int d, int e, int f, int g) { - uint16 *p; - uint32 r; - uint i; - - i = _queue_pos; - - if (i == _queue_end) - return -1; - - if (a==-1) { - _queue_adding = false; - _trigger_count++; - return 0; - } - - p = _cmd_queue[_queue_pos].array; - p[0] = COMMAND_ID; - p[1] = a; - p[2] = b; - p[3] = c; - p[4] = d; - p[5] = e; - p[6] = f; - p[7] = g; - - i = (++i) & (ARRAYSIZE(_cmd_queue)-1); - - if (_queue_end!=i) { - _queue_pos = i; - return 0; - } else { - _queue_pos = (--i) & (ARRAYSIZE(_cmd_queue)-1); - return -1; - } -} - -int SoundEngine::query_queue(int param) { - switch(param) { - case 0: /* get trigger count */ - return _trigger_count; - case 1: /* get trigger type */ - if (_queue_end==_queue_pos) - return -1; - return _cmd_queue[_queue_end].array[1]; - case 2: /* get trigger sound */ - if (_queue_end==_queue_pos) - return 0xFF; - return _cmd_queue[_queue_end].array[2]; - default: - return -1; - } -} - -int SoundEngine::set_master_volume(uint vol) { - int i; - if (vol > 127) - return -1; - _master_volume = vol; - for (i=0; i!=8; i++) - _channel_volume_eff[i] = (_channel_volume[i]+1) * vol >> 7; - update_volumes(); - return 0; -} - -int SoundEngine::get_master_volume() { - return _master_volume; -} - -int SoundEngine::terminate() { - return 0; - /* not implemented */ -} - - -int SoundEngine::enqueue_trigger(int sound, int marker) { - uint16 *p; - uint pos; - - pos = _queue_pos; - - p = _cmd_queue[pos].array; - p[0] = TRIGGER_ID; - p[1] = sound; - p[2] = marker; - - pos = (++pos) & (ARRAYSIZE(_cmd_queue)-1); - if (_queue_end==pos) { - _queue_pos = (--pos) & (ARRAYSIZE(_cmd_queue)-1); - return -1; - } - - _queue_pos = pos; - _queue_adding = true; - _queue_sound = sound; - _queue_marker = marker; - return 0; -} - -int32 SoundEngine::do_command(int a, int b, int c, int d, int e, int f, int g, int h) { - byte cmd = a&0xFF; - byte param = a>>8; - Player *player; - - if (!_initialized && (cmd || param)) - return -1; - - if (param==0) { - switch(cmd) { - case 6: - return set_master_volume(b); - case 7: - return get_master_volume(); - case 8: - return start_sound(b) ? 0 : -1; - case 9: - return stop_sound(b); - case 11: - return stop_all_sounds(); - case 13: - return get_sound_status(b); - case 16: - return set_volchan(b,c); - case 17: - return set_channel_volume(b,c); - case 18: - return set_volchan_entry(b,c); - default: - warning("SoundEngine::do_command invalid command %d", cmd); - } - } else if (param==1) { - - if ( (1<<cmd) & (0x783FFF)) { - player = get_player_byid(b); - if (!player) - return -1; - } - - if ( (1<<cmd) & (1<<11 | 1<<22) ) { - assert(c>=0 && c<=15); - player = (Player*)player->get_part(c); - if(!player) - return -1; - } - - switch(cmd) { - case 0: - return player->get_param(c, d); - case 1: - player->set_priority(c); - return 0; - case 2: - return player->set_vol(c); - case 3: - player->set_pan(c); - return 0; - case 4: - return player->set_transpose(c, d); - case 5: - player->set_detune(c); - return 0; - case 6: - player->set_speed(c); - return 0; - case 7: - return player->jump(c,d,e) ? 0 : -1; - case 8: - return player->scan(c,d,e); - case 9: - return player->set_loop(c,d,e,f,g) ? 0 : -1; - case 10: - player->clear_loop(); - return 0; - case 11: - ((Part*)player)->set_onoff(d!=0); - return 0; - case 12: - return player->_hook.set(c, d, e); - case 13: - return player->fade_vol(c,d); - case 14: - return enqueue_trigger(b,c); - case 15: - return enqueue_command(b,c,d,e,f,g,h); - case 16: - return clear_queue(); - case 19: - return player->get_param(c,d); - case 20: - return player->_hook.set(c,d,e); - case 21: - return -1; - case 22: - ((Part*)player)->set_vol(d); - return 0; - case 23: - return query_queue(b); - case 24: - return 0; - default: - warning("SoundEngine::do_command default midi command %d", cmd); - return -1; - } - } - - return -1; -} - -int SoundEngine::set_channel_volume(uint chan, uint vol) { - if (chan>=8 || vol>127) - return -1; - - _channel_volume[chan] = vol; - _channel_volume_eff[chan] = _master_volume * (vol+1) >> 7; - update_volumes(); - return 0; -} - -void SoundEngine::update_volumes() { - Player *player; - int i; - - for(i=ARRAYSIZE(_players),player=_players; i!=0; i--,player++) { - if (player->_active) - player->set_vol(player->_volume); - } -} - -int SoundEngine::set_volchan_entry(uint a, uint b) { - if (a >= 8) - return -1; - _volchan_table[a] = b; - return 0; -} - -int HookDatas::query_param(int param, byte chan) { - switch(param) { - case 18: - return _jump; - case 19: - return _transpose; - case 20: - return _part_onoff[chan]; - case 21: - return _part_volume[chan]; - case 22: - return _part_program[chan]; - case 23: - return _part_transpose[chan]; - default: - return -1; - } -} - -int HookDatas::set(byte cls, byte value, byte chan) { - switch(cls) { - case 0: - _jump = value; - break; - case 1: - _transpose = value; - break; - case 2: - if (chan<16) - _part_onoff[chan] = value; - else if (chan==16) - memset(_part_onoff, value, 16); - break; - case 3: - if (chan<16) - _part_volume[chan] = value; - else if (chan==16) - memset(_part_volume, value, 16); - break; - case 4: - if (chan<16) - _part_program[chan] = value; - else if (chan==16) - memset(_part_program, value, 16); - break; - case 5: - if (chan<16) - _part_transpose[chan] = value; - else if (chan==16) - memset(_part_transpose, value, 16); - break; - default: - return -1; - } - return 0; -} - - -VolumeFader *SoundEngine::allocate_volume_fader() { - VolumeFader *vf; - int i; - - vf = _volume_fader; - for(i=ARRAYSIZE(_volume_fader); vf->active; ) { - vf++; - if (!--i) - return NULL; - } - - vf->active = true; - _active_volume_faders = true; - return vf; -} - -Player *SoundEngine::get_player_byid(int id) { - int i; - Player *player,*found=NULL; - - for(i=ARRAYSIZE(_players),player=_players; i!=0; i--,player++) { - if (player->_active && player->_id==(uint16)id) { - if(found) - return NULL; - found = player; - } - } - return found; -} - -int SoundEngine::get_volchan_entry(uint a) { - if (a<8) - return _volchan_table[a]; - return -1; -} - -int SoundEngine::initialize(Scumm *scumm) { - int i; - if (_initialized) - return -1; - - _s = scumm; - - _master_volume = 127; - for (i=0; i!=8; i++) - _channel_volume[i] = _channel_volume_eff[i] = _volchan_table[i] = 127; - - init_players(); - init_sustaining_notes(); - init_volume_fader(); - init_queue(); - init_parts(); - midiInit(); - - _initialized = true; - - return 0; -} - -void SoundEngine::init_queue() { - _queue_adding = false; - _queue_pos = 0; - _queue_end = 0; - _trigger_count = 0; -} - -void SoundEngine::pause(bool paused) { - Part *part; - int i; - MidiChannel *mc; - - lock(); - - for (i=ARRAYSIZE(_parts),part=_parts; i!=0; i--, part++) { - if (part->_player) { - if (paused) { - part->_vol_eff = 0; - } else { - part->set_vol(part->_vol); - } - part->vol_changed(); - } - } - - _paused = paused; - - unlock(); -} - - -/*************************************************************************/ - -int Player::fade_vol(byte vol, int time) { - VolumeFader *vf; - int i; - - cancel_volume_fade(); - if (time==0) { - set_vol(vol); - return 0; - } - - vf = _se->allocate_volume_fader(); - if (vf==NULL) - return -1; - - vf->player = this; - vf->num_steps = vf->speed_lo_max = time; - vf->curvol = _volume; - i = (vol - vf->curvol); - vf->speed_hi = i / time; - if (i<0) { - i = -i; - vf->direction = -1; - } else { - vf->direction = 1; - } - vf->speed_lo = i % time; - vf->speed_lo_counter = 0; - return 0; -} - -void Player::clear() { - uninit_seq(); - cancel_volume_fade(); - uninit_parts(); - _active = false; - _ticks_per_beat = TICKS_PER_BEAT; -} - -bool Player::start_sound(int sound) { - void *mdhd; - - mdhd = _se->findTag(sound, MDHD_TAG, 0); - if (mdhd==NULL) - return false; - - _parts = NULL; - _active = true; - _id = sound; - _priority = 0x80; - _volume = 0x7F; - _vol_chan = 0xFFFF; - - _vol_eff = (_se->get_channel_volume(0xFFFF)<<7)>>7; - - _pan = 0; - _transpose = 0; - _detune = 0; - - hook_clear(); - if (start_seq_sound(sound) != 0) { - _active = false; - return false; - } - return true; -} - -void Player::hook_clear() { - memset(&_hook, 0, sizeof(_hook)); -} - -int Player::start_seq_sound(int sound) { - byte *ptr, *track_ptr; - - _song_index = sound; - _timer_counter = 0; - _loop_to_beat = 1; - _loop_from_beat = 1; - _track_index = 0; - _loop_counter = 0; - _loop_to_tick = 0; - _loop_from_tick = 0; - - set_tempo(500000); - set_speed(128); - ptr = _se->findTag(sound, "MTrk", _track_index); - if (ptr==NULL) - return -1; - - track_ptr = ptr; - _cur_pos = _next_pos = get_delta_time(&track_ptr); - _song_offset = track_ptr - ptr; - - _tick_index = _cur_pos; - _beat_index = 1; - - if (_tick_index >= _ticks_per_beat) { - _beat_index += _tick_index/_ticks_per_beat; - _tick_index %= _ticks_per_beat; - } - - return 0; -} - -void Player::set_tempo(uint32 b) { - uint32 i,j; - - i = TEMPO_BASE; - j = _tempo = b; - - while (i&0xFFFF0000 || j&0xFFFF0000) { i>>=1; j>>=1; } - - _tempo_eff = (i<<16) / j; - - set_speed(_speed); -} - -void Player::cancel_volume_fade() { - VolumeFader *vf = _se->_volume_fader; - int i; - - for (i=0; i<8; i++,vf++) { - if (vf->active && vf->player==this) - vf->active = false; - } -} - -void Player::uninit_parts() { - if (_parts && _parts->_player != this) - error("asd"); - while(_parts) - _parts->uninit(); -} - -void Player::uninit_seq() { - _abort = true; -} - -void Player::set_speed(byte speed) { - _speed = speed; - _timer_speed = (_tempo_eff * speed >> 7); -} - -byte *Player::parse_midi(byte *s) { - byte cmd,chan,note,velocity,control; - uint value; - Part *part; - - cmd = *s++; - - chan = cmd&0xF; - - switch(cmd>>4) { - case 0x8: /* key off */ - note = *s++; - if (!_scanning) { - key_off(chan, note); - } else { - clear_active_note(chan, note); - } - s++; /* skip velocity */ - break; - - case 0x9: /* key on */ - note = *s++; - velocity = *s++; - if (velocity) { - if (!_scanning) - key_on(chan, note,velocity); - else - set_active_note(chan,note); - } else { - if (!_scanning) - key_off(chan, note); - else - clear_active_note(chan,note); - } - break; - - case 0xA: /* aftertouch */ - s += 2; - break; - - case 0xB: /* control change */ - control = *s++; - value = *s++; - part = get_part(chan); - if (!part) - break; - - switch(control) { - case 1: /* modulation wheel */ - part->set_modwheel(value); - break; - case 7: /* volume */ - part->set_vol(value); - break; - case 10: /* pan position */ - part->set_pan(value - 0x40); - break; - case 16: /* pitchbend factor */ - part->set_pitchbend_factor(value); - break; - case 17: /* gp slider 2 */ - part->set_detune(value - 0x40); - break; - case 18: /* gp slider 3 */ - part->set_pri(value - 0x40, true); - break; - case 64: /* hold pedal */ - part->set_pedal(value!=0); - break; - case 91: /* effects level */ - part->set_effect_level(value); - break; - case 93: /* chorus */ - part->set_chorus(value); - break; - default: - warning("parse_midi: invalid control %d", control); - } - break; - - case 0xC: /* program change */ - value = *s++; - part = get_part(chan); - if (part) - part->set_program(value); - break; - - case 0xD: /* channel pressure */ - s++; - break; - - case 0xE: /* pitch bend */ - part = get_part(chan); - if (part) - part->set_pitchbend(((s[1]-0x40)<<7)|s[0]); - s+=2; - break; - - case 0xF: - if (chan==0) { - uint size = get_delta_time(&s); - if (*s==SYSEX_ID) - parse_sysex(s,size); - s += size; - } else if (chan==0xF) { - cmd = *s++; - if (cmd==47) - goto Error; /* end of song */ - if (cmd==81) { - set_tempo((s[1]<<16) | (s[2]<<8) | s[3]); - s+=4; - break; - } - s += get_delta_time(&s); - } else if (chan==0x7) { - s += get_delta_time(&s); - } else { - goto Error; - } - break; - - default: -Error:; - if(!_scanning) - clear(); - return NULL; - } - return s; -} - -void Player::parse_sysex(byte *p, uint len) { - byte code; - byte a; - uint b; - byte buf[128]; - Part *part; - - /* too big? */ - if (len>=sizeof(buf)*2) - return; - - /* skip sysex manufacturer */ - p++; - len -= 2; - - switch(code=*p++) { - case 16: - a = *p++ & 0x0F; - if (HARDWARE_TYPE != *p++) - break; - decode_sysex_bytes(p, buf, len - 3); - part = get_part(a); - if(part) - part->set_instrument(buf); - break; - - case 17: - p++; - if (HARDWARE_TYPE != *p++) - break; - a=*p++; - decode_sysex_bytes(p, buf, len - 4); - _se->set_instrument(a, buf); - break; - - case 33: /* param adjust */ - a = *p++ & 0x0F; - if (HARDWARE_TYPE != *p++) - break; - decode_sysex_bytes(p, buf, len - 3); - part = get_part(a); - if (part) - part->set_chan_param(read_word(buf),read_word(buf+2)); - break; - - case 48: /* hook - jump */ - if (_scanning) - break; - decode_sysex_bytes(p+1,buf,len-2); - maybe_jump(buf); - break; - - case 49: /* hook - global transpose */ - decode_sysex_bytes(p+1,buf,len-2); - maybe_set_transpose(buf); - break; - - case 50: /* hook - part on/off */ - buf[0] = *p++ & 0x0F; - decode_sysex_bytes(p,buf+1,len-2); - maybe_part_onoff(buf); - break; - - case 51: /* hook - set volume */ - buf[0] = *p++ & 0x0F; - decode_sysex_bytes(p,buf+1,len-2); - maybe_set_volume(buf); - break; - - case 52: /* hook - set program */ - buf[0] = *p++ & 0x0F; - decode_sysex_bytes(p,buf+1,len-2); - maybe_set_program(buf); - break; - - case 53: /* hook - set transpose */ - buf[0] = *p++ & 0x0F; - decode_sysex_bytes(p,buf+1,len-2); - maybe_set_transpose_part(buf); - break; - - case 64: /* marker */ - p++; - len -= 2; - while (len--) { - _se->handle_marker(_id, *p++); - } - break; - - case 80: /* loop */ - decode_sysex_bytes(p+1,buf,len-2); - set_loop( - read_word(buf), - read_word(buf+2), - read_word(buf+4), - read_word(buf+6), - read_word(buf+8) - ); - break; - - case 81: /* end loop */ - clear_loop(); - break; - - case 96: /* set instrument */ - part = get_part(p[0] & 0x0F); - b = (p[1]&0x0F)<<12 | (p[2]&0x0F)<<8 | (p[4]&0x0F)<<4 | (p[4]&0x0F); - if(part) - part->set_instrument(b); - break; - - default: - debug(6,"unknown sysex %d", code); - } -} - -void Player::decode_sysex_bytes(byte *src, byte *dst, int len) { - while(len>=0) { - *dst++ = (src[0]<<4)|(src[1]&0xF); - src += 2; - len -= 2; - } -} - -void Player::maybe_jump(byte *data) { - byte cmd; - - cmd = data[0]; - - /* is this the hook i'm waiting for? */ - if (cmd && _hook._jump!=cmd) - return; - - /* reset hook? */ - if(cmd!=0 && cmd<0x80) - _hook._jump = 0; - - jump(read_word(data+1), read_word(data+3), read_word(data+5)); -} - -void Player::maybe_set_transpose(byte *data) { - byte cmd; - - cmd = data[0]; - - /* is this the hook i'm waiting for? */ - if (cmd && _hook._transpose!=cmd) - return; - - /* reset hook? */ - if(cmd!=0 && cmd<0x80) - _hook._transpose = 0; - - set_transpose(data[1], (int8)data[2]); -} - -void Player::maybe_part_onoff(byte *data) { - byte cmd,*p; - uint chan; - Part *part; - - cmd = data[1]; - chan = data[0]; - - p = &_hook._part_onoff[chan]; - - /* is this the hook i'm waiting for? */ - if (cmd && *p!=cmd) - return; - - if (cmd!=0 && cmd<0x80) - *p = 0; - - part = get_part(chan); - if (part) - part->set_onoff(data[2]!=0); -} - -void Player::maybe_set_volume(byte *data) { - byte cmd; - byte *p; - uint chan; - Part *part; - - cmd = data[1]; - chan = data[0]; - - p = &_hook._part_volume[chan]; - - /* is this the hook i'm waiting for? */ - if (cmd && *p!=cmd) - return; - - /* reset hook? */ - if (cmd!=0 && cmd<0x80) - *p = 0; - - part = get_part(chan); - if (part) - part->set_vol(data[2]); -} - -void Player::maybe_set_program(byte *data) { - byte cmd; - byte *p; - uint chan; - Part *part; - - cmd = data[1]; - chan = data[0]; - - /* is this the hook i'm waiting for? */ - p = &_hook._part_program[chan]; - - if (cmd && *p!=cmd) - return; - - if (cmd!=0 && cmd<0x80) - *p = 0; - - part = get_part(chan); - if (part) - part->set_program(data[2]); -} - -void Player::maybe_set_transpose_part(byte *data) { - byte cmd; - byte *p; - uint chan; - - cmd = data[1]; - chan = data[0]; - - /* is this the hook i'm waiting for? */ - p = &_hook._part_transpose[chan]; - - if (cmd && *p!=cmd) - return; - - /* reset hook? */ - if (cmd!=0 && cmd<0x80) - *p = 0; - - part_set_transpose(chan, data[2], (int8)data[3]); -} - -int Player::set_transpose(byte relative, int b) { - Part *part; - - if (b>24 || b<-24 || relative>1) - return -1; - if (relative) - b = transpose_clamp(_transpose + b, -7, 7); - - _transpose = b; - - for(part=_parts; part; part=part->_next) { - part->set_transpose(part->_transpose); - } - - return 0; -} - -void Player::clear_active_notes() { - memset(_se->_active_notes, 0, sizeof(_se->_active_notes)); -} - -void Player::clear_active_note(int chan, byte note) { - _se->_active_notes[note] &= ~(1<<chan); -} - -void Player::set_active_note(int chan, byte note) { - _se->_active_notes[note] |= (1<<chan); -} - -void Player::part_set_transpose(uint8 chan, byte relative, int8 b) { - Part *part; - - if (b>24 || b<-24) - return; - - part = get_part(chan); - if (!part) - return; - if (relative) - b = transpose_clamp(b + part->_transpose, -7, 7); - part->set_transpose(b); -} - -void Player::key_on(uint8 chan, uint8 note, uint8 velocity) { - Part *part; - - part = get_part(chan); - if (!part || !part->_on) - return; - - part->key_on(note, velocity); -} - -void Player::key_off(uint8 chan, uint8 note) { - Part *part; - - for(part=_parts; part; part = part->_next) { - if (part->_chan==(byte)chan && part->_on) - part->key_off(note); - } -} - -bool Player::jump(uint track, uint beat, uint tick) { - byte *mtrk, *cur_mtrk, *scanpos; - uint32 topos,curpos,track_offs; - - if (!_active) - return false; - - mtrk = _se->findTag(_song_index, "MTrk", track); - if (!mtrk) - return false; - - cur_mtrk = _se->findTag(_song_index,"MTrk", _track_index); - if (!cur_mtrk) - return false; - - _se->lock(); - - if (beat==0) - beat=1; - - topos = (beat-1) * _ticks_per_beat + tick; - - if (track == _track_index && topos >= _cur_pos) { - scanpos = _song_offset + mtrk; - curpos = _next_pos; - } else { - scanpos = mtrk; - curpos = get_delta_time(&scanpos); - } - - while (curpos < topos) { - skip_midi_cmd(&scanpos); - if (!scanpos) { - _se->unlock(); - return false; - } - curpos += get_delta_time(&scanpos); - } - - track_offs = scanpos - mtrk; - - turn_off_pedals(); - - find_sustaining_notes(cur_mtrk+_song_offset, mtrk+track_offs, curpos-topos); - - _beat_index = beat; - _tick_index = tick; - _cur_pos = topos; - _next_pos = curpos; - _timer_counter = 0; - _song_offset = track_offs; - if (track != _track_index) { - _track_index = track; - _loop_counter = 0; - } - _abort = true; - _se->unlock(); - return true; -} - -bool Player::set_loop(uint count, uint tobeat, uint totick, uint frombeat, uint fromtick) { - if (tobeat+1 >= frombeat) - return false; - - if (tobeat==0) - tobeat=1; - - _loop_counter = 0; /* because of possible interrupts */ - _loop_to_beat = tobeat; - _loop_to_tick = totick; - _loop_from_beat = frombeat; - _loop_from_tick = fromtick; - _loop_counter = count; - - return true; -} - -void Player::clear_loop() { - _loop_counter = 0; -} - -void Player::turn_off_pedals() { - Part *part; - - for(part=_parts; part; part = part->_next) { - if (part->_pedal) - part->set_pedal(false); - } -} - -void Player::find_sustaining_notes(byte *a, byte *b, uint32 l) { - uint32 pos; - uint16 mask; - uint16 *bitlist_ptr; - SustainingNotes *sn,*next; - IsNoteCmdData isnote; - int j; - uint num_active; - uint max_off_pos; - - num_active = update_actives(); - - /* pos contains number of ticks since current position */ - pos = _next_pos - _cur_pos; - if ((int32)pos<0) - pos = 0; - - /* locate the positions where the notes are turned off. - * remember each note that was turned off - */ - while (num_active != 0) { - /* is note off? */ - j = is_note_cmd(&a,&isnote); - if (j==-1) - break; - if (j == 1) { - mask = 1<<isnote.chan; - bitlist_ptr = _se->_active_notes + isnote.note; - if (*bitlist_ptr & mask) { - *bitlist_ptr &= ~mask; - num_active--; - /* Get a node from the free list */ - if ((sn=_se->_sustain_notes_free) == NULL) - return; - _se->_sustain_notes_free = sn->next; - - /* Insert it in the beginning of the used list */ - sn->next = _se->_sustain_notes_used; - _se->_sustain_notes_used = sn; - sn->prev = NULL; - if (sn->next) - sn->next->prev = sn; - - sn->note = isnote.note; - sn->chan = isnote.chan; - sn->player = this; - sn->off_pos = pos; - sn->pos = 0; - sn->counter = 0; - } - } - pos += get_delta_time(&a); - } - - /* find the maximum position where a note was turned off */ - max_off_pos = 0; - for(sn=_se->_sustain_notes_used; sn; sn = sn->next) { - _se->_active_notes[sn->note] |= (1<<sn->chan); - if (sn->off_pos > max_off_pos) { - max_off_pos = sn->off_pos; - } - } - - /* locate positions where notes are turned on */ - pos = l; - while (pos < max_off_pos) { - j = is_note_cmd(&b,&isnote); - if (j==-1) - break; - if (j == 2) { - mask = 1<<isnote.chan; - bitlist_ptr = _se->_active_notes + isnote.note; - - if (*bitlist_ptr&mask) { - sn = _se->_sustain_notes_used; - while (sn) { - next = sn->next; - if (sn->note==isnote.note && sn->chan==isnote.chan && pos < sn->off_pos) { - *bitlist_ptr &= ~mask; - /* Unlink from the sustain list */ - if (next) - next->prev = sn->prev; - if (sn->prev) - sn->prev->next = next; - else - _se->_sustain_notes_used = next; - /* Insert into the free list */ - sn->next = _se->_sustain_notes_free; - _se->_sustain_notes_free = sn; - } - sn = next; - } - } - } - pos += get_delta_time(&b); - } - - /* Concatenate head and used list */ - if (!_se->_sustain_notes_head) { - _se->_sustain_notes_head = _se->_sustain_notes_used; - _se->_sustain_notes_used = NULL; - return; - } - sn = _se->_sustain_notes_head; - while (sn->next) sn = sn->next; - sn->next = _se->_sustain_notes_used; - _se->_sustain_notes_used = NULL; - if (sn->next) - sn->next->prev = sn; -} - -Part *Player::get_part(uint8 chan) { - Part *part; - - part = _parts; - while (part) { - if (part->_chan == chan) - return part; - part = part->_next; - } - - part = _se->allocate_part(_priority); - if (!part) { - warning("no parts available"); - return NULL; - } - - part->_chan = chan; - part->setup(this); - - return part; -} - -uint Player::update_actives() { - Part *part; - MidiChannel *mc; - uint16 *active; - int count = 0; - - clear_active_notes(); - active = _se->_active_notes; - for(part=_parts; part; part = part->_next) { - if (part->_mc) - count += part->update_actives(active); - } - return count; -} - -void Player::set_priority(int pri) { - Part *part; - - _priority = pri; - for(part=_parts; part; part = part->_next) { - part->set_pri(part->_pri, false); - } - _se->adjust_priorities(); -} - -void Player::set_pan(int pan) { - Part *part; - - _pan = pan; - for(part=_parts; part; part = part->_next) { - part->set_pan(part->_pan); - } -} - -void Player::set_detune(int detune) { - Part *part; - - _detune = detune; - for(part=_parts; part; part = part->_next) { - part->set_detune(part->_detune); - } -} - -int Player::scan(uint totrack, uint tobeat, uint totick) { - byte *mtrk,*scanptr; - uint32 curpos,topos; - uint32 pos; - - assert(totrack>=0 && tobeat>=0 && totick>=0); - - if (!_active) - return -1; - - mtrk = _se->findTag(_song_index, "MTrk", totrack); - if (!mtrk) - return -1; - - _se->lock(); - if (tobeat==0) - tobeat++; - - silence_parts(); - clear_active_notes(); - scanptr = mtrk; - curpos = get_delta_time(&scanptr); - _scanning=true; - - topos = (tobeat-1) * _ticks_per_beat + totick; - - while (curpos < topos) { - scanptr = parse_midi(scanptr); - if (!scanptr) { - _scanning=false; - _se->unlock(); - return -1; - } - curpos += get_delta_time(&scanptr); - } - pos = scanptr - mtrk; - - _scanning=false; - play_active_notes(); - _beat_index = tobeat; - _tick_index = totick; - _cur_pos = topos; - _next_pos = curpos; - _timer_counter = 0; - _song_offset = pos; - if (_track_index != totrack) { - _track_index = totrack; - _loop_counter = 0; - } - _se->unlock(); - return 0; -} - -void Player::silence_parts() { - Part *part; - - for(part=_parts; part; part = part->_next) - if (part->_mc) - part->silence(); -} - -void Player::play_active_notes() { - int i,j; - uint mask; - - for (i=0; i!=128; i++) { - mask = _se->_active_notes[i]; - for (j=0; j!=16; j++,mask>>=1) { - if (mask&1) { - key_on(j, i, 80); - } - } - } -} - -int Player::set_vol(byte vol) { - Part *part; - - if (vol > 127) - return -1; - - _volume = vol; - _vol_eff = _se->get_channel_volume(_vol_chan) * (vol + 1) >> 7; - - for(part=_parts; part; part=part->_next) { - part->set_vol(part->_vol); - } - - return 0; -} - -int Player::get_param(int param, byte chan) { - switch(param) { - case 0: - return (byte)_priority; - case 1: - return (byte)_volume; - case 2: - return (byte)_pan; - case 3: - return (byte)_transpose; - case 4: - return (byte)_detune; - case 5: - return _speed; - case 6: - return _track_index; - case 7: - return _beat_index; - case 8: - return _tick_index; - case 9: - return _loop_counter; - case 10: - return _loop_to_beat; - case 11: - return _loop_to_tick; - case 12: - return _loop_from_beat; - case 13: - return _loop_from_tick; - case 14: case 15: case 16: case 17: - return query_part_param(param, chan); - case 18: case 19: case 20: case 21: case 22: case 23: - return _hook.query_param(param, chan); - default: - return -1; - } -} - -int Player::query_part_param(int param, byte chan) { - Part *part; - - part = _parts; - while (part) { - if(part->_chan==chan) { - switch(param) { - case 14: - return part->_on; - case 15: - return part->_vol; - case 16: - return part->_program; - case 17: - return part->_transpose; - default: - return -1; - } - } - part = part->_next; - } - return 129; -} - -/*******************************************************************/ - -#define OFFS(type,item) ((int)(&((type*)0)->item)) -#define SIZE(type,item) sizeof(((type*)0)->item) -#define MKLINE(type,item,saveas) {OFFS(type,item),saveas,SIZE(type,item)} -#define MKARRAY(type,item,saveas,num) {OFFS(type,item),128|saveas,SIZE(type,item)}, {num,0,0} -#define MKEND() {0xFFFF,0xFF,0xFF} - -#define MKREF(type,item,refid) {OFFS(type,item),refid,0xFF} - -enum { - TYPE_PART = 1, - TYPE_PLAYER = 2, -}; - -int SoundEngine::saveReference(SoundEngine *me, byte type, void*ref) { - switch(type) { - case TYPE_PART: return (Part*)ref - me->_parts; - case TYPE_PLAYER: return (Player*)ref - me->_players; - default: - error("saveReference: invalid type"); - } -} - -void *SoundEngine::loadReference(SoundEngine *me, byte type, int ref) { - switch(type) { - case TYPE_PART: return &me->_parts[ref]; - case TYPE_PLAYER: return &me->_players[ref]; - default: - error("loadReference: invalid type"); - } -} - -int SoundEngine::save_or_load(Serializer *ser) { - const SaveLoadEntry mainEntries[] = { - MKLINE(SoundEngine,_queue_end, sleUint8), - MKLINE(SoundEngine,_queue_pos, sleUint8), - MKLINE(SoundEngine,_queue_sound, sleUint16), - MKLINE(SoundEngine,_queue_adding, sleByte), - MKLINE(SoundEngine,_queue_marker, sleByte), - MKLINE(SoundEngine,_queue_cleared, sleByte), - MKLINE(SoundEngine,_master_volume, sleByte), - MKLINE(SoundEngine,_trigger_count, sleUint16), - MKARRAY(SoundEngine,_channel_volume[0], sleUint16, 8), - MKARRAY(SoundEngine,_volchan_table[0], sleUint16, 8), - MKEND() - }; - - const SaveLoadEntry playerEntries[] = { - MKREF(Player,_parts,TYPE_PART), - MKLINE(Player,_active,sleByte), - MKLINE(Player,_id,sleUint16), - MKLINE(Player,_priority,sleByte), - MKLINE(Player,_volume,sleByte), - MKLINE(Player,_pan,sleInt8), - MKLINE(Player,_transpose,sleByte), - MKLINE(Player,_detune,sleInt8), - MKLINE(Player,_vol_chan,sleUint16), - MKLINE(Player,_vol_eff,sleByte), - MKLINE(Player,_speed,sleByte), - MKLINE(Player,_song_index,sleUint16), - MKLINE(Player,_track_index,sleUint16), - MKLINE(Player,_timer_counter,sleUint16), - MKLINE(Player,_loop_to_beat,sleUint16), - MKLINE(Player,_loop_from_beat,sleUint16), - MKLINE(Player,_loop_counter,sleUint16), - MKLINE(Player,_loop_to_tick,sleUint16), - MKLINE(Player,_loop_from_tick,sleUint16), - MKLINE(Player,_tempo,sleUint32), - MKLINE(Player,_cur_pos,sleUint32), - MKLINE(Player,_next_pos,sleUint32), - MKLINE(Player,_song_offset,sleUint32), - MKLINE(Player,_tick_index,sleUint16), - MKLINE(Player,_beat_index,sleUint16), - MKLINE(Player,_ticks_per_beat,sleUint16), - MKLINE(Player,_hook._jump,sleByte), - MKLINE(Player,_hook._transpose,sleByte), - MKARRAY(Player,_hook._part_onoff[0],sleByte,16), - MKARRAY(Player,_hook._part_volume[0],sleByte,16), - MKARRAY(Player,_hook._part_program[0],sleByte,16), - MKARRAY(Player,_hook._part_transpose[0],sleByte,16), - MKEND() - }; - - const SaveLoadEntry volumeFaderEntries[] = { - MKREF(VolumeFader,player,TYPE_PLAYER), - MKLINE(VolumeFader,active,sleUint8), - MKLINE(VolumeFader,curvol,sleUint8), - MKLINE(VolumeFader,speed_lo_max,sleUint16), - MKLINE(VolumeFader,num_steps,sleUint16), - MKLINE(VolumeFader,speed_hi,sleInt8), - MKLINE(VolumeFader,direction,sleInt8), - MKLINE(VolumeFader,speed_lo,sleInt8), - MKLINE(VolumeFader,speed_lo_counter,sleUint16), - MKEND() - }; - - const SaveLoadEntry partEntries[] = { - MKREF(Part,_next,TYPE_PART), - MKREF(Part,_prev,TYPE_PART), - MKREF(Part,_player,TYPE_PLAYER), - MKLINE(Part,_pitchbend,sleInt16), - MKLINE(Part,_pitchbend_factor,sleUint8), - MKLINE(Part,_transpose,sleInt8), - MKLINE(Part,_vol,sleUint8), - MKLINE(Part,_detune,sleInt8), - MKLINE(Part,_pan,sleInt8), - MKLINE(Part,_on,sleUint8), - MKLINE(Part,_modwheel,sleUint8), - MKLINE(Part,_pedal,sleUint8), - MKLINE(Part,_program,sleUint8), - MKLINE(Part,_pri,sleUint8), - MKLINE(Part,_chan,sleUint8), - MKLINE(Part,_effect_level,sleUint8), - MKLINE(Part,_chorus,sleUint8), - MKLINE(Part,_gmidi_5,sleUint8), - MKLINE(Part,_gmidi_1,sleUint8), - MKEND() - }; - - if (!ser->isSaving()) { - stop_all_sounds(); - } - - ser->_ref_me = this; - ser->_saveload_ref = ser->isSaving() ? ((void*)&saveReference) : ((void*)&loadReference); - - ser->saveLoadEntries(this, mainEntries); - ser->saveLoadArrayOf(_players, ARRAYSIZE(_players), sizeof(_players[0]), playerEntries); - ser->saveLoadArrayOf(_parts, ARRAYSIZE(_parts),sizeof(_parts[0]), partEntries); - ser->saveLoadArrayOf(_volume_fader,ARRAYSIZE(_volume_fader), - sizeof(_volume_fader[0]), volumeFaderEntries); - - if (!ser->isSaving()) { - /* Load all sounds that we need */ - int i; - fix_players_after_load(); - init_sustaining_notes(); - _active_volume_faders = true; - fix_parts_after_load(); - adjust_priorities(); - } - - return 0; -} - -void SoundEngine::fix_parts_after_load() { - Part *part; - int i; - - for (i=ARRAYSIZE(_parts),part=_parts; i!=0; i--, part++) { - if (part->_player) - part->fix_after_load(); - } -} - -void SoundEngine::fix_players_after_load() { - Player *player = _players; - int i; - - for (i=ARRAYSIZE(_players); i!=0; i--, player++) { - if (player->_active) { - player->set_tempo(player->_tempo); - _s->getResourceAddress(rtSound, player->_id); - } - } -} - -void Part::fix_after_load() { - set_transpose(_transpose); - set_vol(_vol); - set_detune(_detune); - set_pri(_pri,false); - set_pan(_pan); -} - -void Part::key_on(byte note, byte velocity) { - if (_mc) { - _mc->_actives[note>>4] |= (1<<(note&0xF)); - _se->midiNoteOn(_mc->_chan, note, velocity); - } else if (_gmidi_5) { - _se->midiVolume(SPECIAL_CHANNEL, _vol_eff); - _se->midiProgram(SPECIAL_CHANNEL, _gmidi_1); - _se->midiNoteOn(SPECIAL_CHANNEL, note, velocity); - } -} - -void Part::key_off(byte note) { - if (_mc) { - _mc->_actives[note>>4] &= ~(1<<(note&0xF)); - _se->midiNoteOff(_mc->_chan, note); - } else if (_gmidi_5) { - _se->midiNoteOff(SPECIAL_CHANNEL, note); - } -} - -void Part::init(SoundEngine *se) { - _se = se; - _player = NULL; - _next = NULL; - _prev = NULL; - _mc = NULL; -} - -void Part::setup(Player *player) { - _player = player; - - /* Insert first into player's list */ - _prev = NULL; - _next = player->_parts; - if (player->_parts) - player->_parts->_prev = this; - player->_parts = this; - - _gmidi_5 = true; - _on = true; - _pri_eff = player->_priority; - _pri = 0; - _vol = 127; - _vol_eff = player->_vol_eff; - _pan = clamp(player->_pan, -64, 63); - _transpose_eff = player->_transpose; - _transpose = 0; - _detune = 0; - _detune_eff = player->_detune; - _pitchbend_factor = 2; - _pitchbend = 0; - _effect_level = 64; - _program = 255; - _chorus = 0; - _modwheel = 0; - _gmidi_1 = 0; - _pedal = false; - _mc = NULL; -} - -void Part::uninit() { - if (!_player) - return; - off(); - - /* unlink */ - if (_next) - _next->_prev = _prev; - if (_prev) - _prev->_next = _next; - else - _player->_parts = _next; - _player = NULL; - _next = NULL; - _prev = NULL; -} - -void Part::off() { - if (_mc) { - silence(); - _mc->_part = NULL; - _mc = NULL; - } -} - -void Part::silence() { - memset(_mc->_actives, 0, sizeof(_mc->_actives)); - _se->midiSilence(_mc->_chan); -} - -void Part::set_detune(int8 detune) { - _detune_eff = clamp((_detune=detune) + _player->_detune, -128, 127); - mod_changed(); -} - -void Part::set_pitchbend(int value) { - _pitchbend = value * _pitchbend_factor >> 6; - mod_changed(); -} - -void Part::set_vol(uint8 vol) { - _vol_eff = ((_vol=vol)+1)*_player->_vol_eff >> 7; - vol_changed(); -} - -void Part::set_pri(int8 pri, bool recalc) { - _pri_eff = clamp((_pri=pri) + _player->_priority, 0, 255); - if (recalc) - _se->adjust_priorities(); -} - -void Part::set_pan(int8 pan) { - _pan_eff = clamp((_pan=pan) + _player->_pan, -64, 63); - pan_changed(); -} - -void Part::set_transpose(int8 transpose) { - _transpose_eff = transpose_clamp((_transpose=transpose) + - _player->_transpose, -12, 12); - mod_changed(); -} - -void Part::set_pedal(bool value) { - _pedal = value; - pedal_changed(); -} - -void Part::set_modwheel(uint value) { - _modwheel = value; - modwheel_changed(); -} - -void Part::set_chorus(uint chorus) { - _chorus = chorus; - chorus_changed(); -} - -void Part::set_effect_level(uint level) { - _effect_level = level; - effect_level_changed(); -} - -void Part::set_program(byte program) { - if (_program!=program || _gmidi_1!=0) { - _program = program; - _gmidi_1 = 0; - program_changed(); - if (_gmidi_5) { - _gmidi_5 = false; - _se->adjust_priorities(); - } - } -} - -void Part::set_instrument(uint b) { - _gmidi_1 = (byte)(b>>8); - _program = (byte)b; - - if (_program < 128) { - program_changed(); - if(_gmidi_5) { - _gmidi_5 = false; - _se->adjust_priorities(); - } - } -} - -void Part::set_pitchbend_factor(uint8 value) { - if (value > 12) - return; - set_pitchbend(0); - _pitchbend_factor = value; -} - -void Part::set_onoff(bool on) { - if (_on != on) { - _on = on; - if (!on) - off(); - if (!_gmidi_5) - _se->adjust_priorities(); - } -} - -void Part::mod_changed() { - if (_mc) { - _se->midiPitchBend(_mc->_chan, clamp(_pitchbend + _detune_eff + (_transpose_eff<<7), -2048, 2047)); - } -} - -void Part::vol_changed() { - if (_mc) { - _se->midiVolume(_mc->_chan, _vol_eff); - } -} - -void Part::pedal_changed() { - if (_mc) { - _se->midiPedal(_mc->_chan, _pedal); - } -} - -void Part::modwheel_changed() { - if (_mc) { - _se->midiModWheel(_mc->_chan, _modwheel); - } -} - -void Part::effect_level_changed() { - if (_mc) { - _se->midiEffectLevel(_mc->_chan, _effect_level); - } -} - -void Part::chorus_changed() { - if (_mc) { - _se->midiChorus(_mc->_chan, _effect_level); - } -} - -void Part::program_changed() { - if (_mc) { - if (_gmidi_1) { - _se->midiControl0(_mc->_chan, _gmidi_1); - _se->midiProgram(_mc->_chan, _program); - _se->midiControl0(_mc->_chan, 0); - } else { - _se->midiProgram(_mc->_chan, _program); - } - } -} - -void Part::pan_changed() { - if (_mc) { - _se->midiPan(_mc->_chan, _pan_eff); - } -} - -int Part::update_actives(uint16 *active) { - int i,j; - uint16 *act,mask,bits; - int count = 0; - - bits = 1<<_chan; - - act = _mc->_actives; - - for(i=8; i; i--) { - mask = *act++; - if (mask) { - for(j=16; j; j--,mask>>=1,active++) { - if (mask&1 && !(*active&bits)) { - *active|=bits; - count++; - } - } - } else { - active += 16; - } - } - return count; -} - -void MidiChannel::init(byte chan) { - int i; - - _part = NULL; - _chan = chan; - - memset(_actives, 0, sizeof(_actives)); -} - -void SoundEngine::lock() { - _locked++; -} - -void SoundEngine::unlock() { - _locked--; -} - - -void SoundEngine::adjust_priorities() { - Part *part,*hipart; - int i; - byte hipri,lopri; - MidiChannel *mc,*lomc; - - while(true) { - hipri = 0; - hipart = NULL; - for(i=32,part=_parts; i; i--,part++) { - if (part->_player && part->_gmidi_5==0 && part->_on && !part->_mc && part->_pri_eff>=hipri) { - hipri = part->_pri_eff; - hipart = part; - } - } - - if (!hipart) - return; - - lopri = 255; - lomc = NULL; - for(i=ARRAYSIZE(_midi_channels),mc=_midi_channels;;mc++) { - if (!mc->_part) { - lomc = mc; - break; - } - if (mc->_part->_pri_eff<=lopri) { - lopri = mc->_part->_pri_eff; - lomc = mc; - } - - if (!--i) { - if (lopri >= hipri) - return; - lomc->_part->off(); - break; - } - } - - hipart->_mc = lomc; - lomc->_part = hipart; - hipart->vol_changed(); - hipart->pan_changed(); - hipart->mod_changed(); - hipart->modwheel_changed(); - hipart->pedal_changed(); - hipart->effect_level_changed(); - hipart->program_changed(); - } -} - -#if defined(WIN32) - -void SoundEngine::midiInit() { - if (midiOutOpen((HMIDIOUT*)&_mo, MIDI_MAPPER, NULL, NULL, 0) != MMSYSERR_NOERROR) - error("midiOutOpen failed"); -} - -#define MIDI_OUT(a,b) midiOutShortMsg((HMIDIOUT)(a), (b)) - -#elif defined(USE_TIMIDITY) - -static int connect_to_timidity(int port) -{ - struct hostent *serverhost; - struct sockaddr_in sadd; - int s; - - serverhost = gethostbyname("localhost"); - if (serverhost == NULL) - error("Could not resolve host"); - sadd.sin_family = serverhost->h_addrtype; - sadd.sin_port = htons(port); - memcpy(&(sadd.sin_addr), serverhost->h_addr_list[0], serverhost->h_length); - - s = socket(AF_INET,SOCK_STREAM,0); - if (s < 0) - error("Could not open socket"); - if (connect(s, (struct sockaddr *) &sadd, sizeof(struct sockaddr_in)) < 0) - error("Could not connect to server"); - - return s; -} - -void SoundEngine::midiInit() { - int s, s2; - int len; - int dummy, newport; - char buf[256]; - - s = connect_to_timidity(7777); - len = read(s, buf, 256); - buf[len] = '\0'; - printf("%s", buf); - - sprintf(buf, "SETBUF %f %f\n", 0.1, 0.15); - write(s, buf, strlen(buf)); - len = read(s, buf, 256); - buf[len] = '\0'; - printf("%s", buf); - - sprintf(buf, "OPEN lsb\n"); - write(s, buf, strlen(buf)); - len = read(s, buf, 256); - buf[len] = '\0'; - printf("%s", buf); - - sscanf(buf, "%d %d", &dummy, &newport); - printf(" => port = %d\n", newport); - - s2 = connect_to_timidity(newport); - _mo = (void *) s2; -} - -#define DEVICE_NUM 0 - -static inline void MIDI_OUT(void *a, int b) { - int s = (int) a; - unsigned char buf[256]; - int position = 0; - - switch (b & 0xF0) { - case 0x80: - case 0x90: - case 0xA0: - case 0xB0: - case 0xE0: - buf[position++] = SEQ_MIDIPUTC; - buf[position++] = b; - buf[position++] = DEVICE_NUM; - buf[position++] = 0; - buf[position++] = SEQ_MIDIPUTC; - buf[position++] = (b >> 8) & 0x7F; - buf[position++] = DEVICE_NUM; - buf[position++] = 0; - buf[position++] = SEQ_MIDIPUTC; - buf[position++] = (b >> 16) & 0x7F; - buf[position++] = DEVICE_NUM; - buf[position++] = 0; - break; - case 0xC0: - case 0xD0: - buf[position++] = SEQ_MIDIPUTC; - buf[position++] = b; - buf[position++] = DEVICE_NUM; - buf[position++] = 0; - buf[position++] = SEQ_MIDIPUTC; - buf[position++] = (b >> 8) & 0x7F; - buf[position++] = DEVICE_NUM; - buf[position++] = 0; - break; - default: - fprintf(stderr, "Unknown : %08x\n", b); - break; - } - write(s, buf, position); -} - -#else -#define MIDI_OUT(a,b) -void SoundEngine::midiInit() { } -#endif - -void SoundEngine::midiPitchBend(byte chan, int16 pitchbend) { - uint16 tmp; - - if (_midi_pitchbend_last[chan] != pitchbend) { - _midi_pitchbend_last[chan] = pitchbend; - tmp = (pitchbend<<2) + 0x2000; - MIDI_OUT(_mo, ((tmp>>7)&0x7F)<<16 | (tmp&0x7F)<<8 | 0xE0 | chan); - } -} - -void SoundEngine::midiVolume(byte chan, byte volume) { - if (_midi_volume_last[chan] != volume) { - _midi_volume_last[chan] = volume; - MIDI_OUT(_mo, volume<<16 | 7<<8 | 0xB0 | chan); - } -} -void SoundEngine::midiPedal(byte chan, bool pedal) { - if (_midi_pedal_last[chan] != pedal) { - _midi_pedal_last[chan] = pedal; - MIDI_OUT(_mo, pedal<<16 | 64<<8 | 0xB0 | chan); - } -} - -void SoundEngine::midiModWheel(byte chan, byte modwheel) { - if (_midi_modwheel_last[chan] != modwheel) { - _midi_modwheel_last[chan] = modwheel; - MIDI_OUT(_mo, modwheel<<16 | 1<<8 | 0xB0 | chan); - } -} - -void SoundEngine::midiEffectLevel(byte chan, byte level) { - if (_midi_effectlevel_last[chan] != level) { - _midi_effectlevel_last[chan] = level; - MIDI_OUT(_mo, level<<16 | 91<<8 | 0xB0 | chan); - } -} - -void SoundEngine::midiChorus(byte chan, byte chorus) { - if (_midi_chorus_last[chan] != chorus) { - _midi_chorus_last[chan] = chorus; - MIDI_OUT(_mo, chorus<<16 | 93<<8 | 0xB0 | chan); - } -} - -void SoundEngine::midiControl0(byte chan, byte value) { - MIDI_OUT(_mo, value<<16 | 0<<8 | 0xB0 | chan); -} - -void SoundEngine::midiProgram(byte chan, byte program) { - MIDI_OUT(_mo, program<<8 | 0xC0 | chan); -} - -void SoundEngine::midiPan(byte chan, int8 pan) { - if (_midi_pan_last[chan] != pan) { - _midi_pan_last[chan] = pan; - MIDI_OUT(_mo, ((pan-64)&0x7F)<<16 | 10<<8 | 0xB0 | chan); - } -} - -void SoundEngine::midiNoteOn(byte chan, byte note, byte velocity) { - MIDI_OUT(_mo, velocity<<16 | note<<8 | 0x90 | chan); -} - -void SoundEngine::midiNoteOff(byte chan, byte note) { - MIDI_OUT(_mo, note<<8 | 0x80 | chan); -} - -void SoundEngine::midiSilence(byte chan) { - MIDI_OUT(_mo, (64<<8)|0xB0|chan); - MIDI_OUT(_mo, (123<<8)|0xB0|chan); -} |