aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--imuse.cpp2647
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);
-}