[Scummvm-cvs-logs] CVS: scummvm/scumm player_v2.h,NONE,2.1 player_v2.cpp,NONE,2.1 module.mk,1.14,1.15 scumm.h,1.215,1.216 scummvm.cpp,2.181,2.182 sound.cpp,1.126,1.127

Jamieson Christian jamieson630 at users.sourceforge.net
Mon May 26 15:04:05 CEST 2003


Update of /cvsroot/scummvm/scummvm/scumm
In directory sc8-pr-cvs1:/tmp/cvs-serv8751

Modified Files:
	module.mk scumm.h scummvm.cpp sound.cpp 
Added Files:
	player_v2.h player_v2.cpp 
Log Message:
Added Hoenicke's PC-speaker waveform generator
and script interpreter for GF_OLD_BUNDLE music resources.

We'll try to get the waveform generator into a
MidiDriver wrapper for use with the 'SPK' resources
of later games, but this is usable for now.

Great work, Hoenicke!

--- NEW FILE: player_v2.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 * Copyright (C) 2001-2003 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: /cvsroot/scummvm/scummvm/scumm/player_v2.h,v 2.1 2003/05/26 22:03:04 jamieson630 Exp $
 *
 */

#ifndef PLAYER_V2_H
#define PLAYER_V2_H

#include "common/scummsys.h"
#include "sound/mixer.h"

struct channel_data {
	uint16 time_left;          // 00
	uint16 next_cmd;           // 02
	uint16 base_freq;          // 04
	uint16 freq_delta;         // 06
	uint16 freq;               // 08
	uint16 volume;             // 10
	uint16 volume_delta;       // 12
	uint16 tempo;              // 14
	uint16 inter_note_pause;   // 16
	uint16 transpose;          // 18
	uint16 note_length;        // 20
	uint16 hull_curve;         // 22
	uint16 hull_offset;        // 24
	uint16 hull_counter;       // 26
	uint16 freqmod_table;      // 28
	uint16 freqmod_offset;     // 30
	uint16 freqmod_incr;       // 32
	uint16 freqmod_multiplier; // 34
	uint16 freqmod_modulo;     // 36
	uint16 unknown[5];         // 38 - 46
	uint16 music_script_nr;    // 48
} GCC_PACK;

union ChannelInfo {
	channel_data d;
	uint16 array[sizeof(channel_data)/2];
};



class Player_V2 {
public:
	Player_V2();
	~Player_V2();

	void startSound(int nr, byte *data);
	void stopSound(int nr);
	void stopAllSounds();
	int  getSoundStatus(int nr);

private:
	SoundMixer *_mixer;
	int _next_tick;

	int sample_rate;
	int ticks_per_sample;
	int ticks_counted;
	int samples_left;
	int freq;
	int last_freq;
	int level;
	int pcjr;
	const uint16 *freqs_table;
	unsigned int decay;

	ChannelInfo channels[4];

	int   current_nr;
	byte *current_data;
	int   next_nr;
	byte *next_data;
	byte *retaddr;

	void execute_cmd(ChannelInfo *channel);
	void next_freqs(ChannelInfo *channel);
	void generate_samples(int16 *buf, int len);
	void on_timer();
	void clear_channel(int i);
	void chainNextSound();

	static void premix_proc(void *param, int16 *buf, uint len);
	void do_mix (int16 *buf, int len);
};

#endif

--- NEW FILE: player_v2.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2003 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: /cvsroot/scummvm/scummvm/scumm/player_v2.cpp,v 2.1 2003/05/26 22:03:04 jamieson630 Exp $
 */

#include "stdafx.h"
#include "common/engine.h"
#include "player_v2.h"

#define FREQ_HZ 236 // Don't change!

const uint8 note_lengths[] = {
	0,  
	0,  0,  2,
	0,  3,  4,
	0,  6,  8,
	0, 12, 16,
	0, 24, 32,
	0, 48, 64
};

static const uint16 hull_offsets[] = {
	0, 12, 24, 36, 48, 60, 
	72, 88, 104, 120, 136, 240, 
	152, 164
};

static const int16 hulls[] = {
	// hull 0
	3, -1, 0, 0, 0, 0, 0, 0,
	0, -1, 0, 0,
	// hull 1 (staccato)
	3, -1, 0, 30, 0, -1, 0, 0,
	0, -1, 0, 0,
	// hull 2 (legato)
	3, -1, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0,
	// hull 3 (staccatissimo)
	3, -1, 0, 2, 0, -1, 0, 0,
	0, -1, 0, 0,
	// hull 4
	3, -1, 0, 6, 0, -1, 0, 0,
	0, -1, 0, 0,
	// hull 5
	3, -1, 0, 10, 0, -1, 0, 0,
	0, -1, 0, 0,
	// hull 6
	(int16) 60000, -1, -1000, 20, 0, 0, 0, 0,
	(int16) 40000, -1, -5000,  5, 0, -1, 0, 0,
	// hull 7
	(int16) 50000, -1, 0, 8, 30000, -1, 0, 0,
	28000, -1, -5000,  5, 0, -1, 0, 0,
	// hull 8
	(int16) 60000, -1, -2000, 16, 0, 0, 0, 0,
	28000, -1, -6000,  5, 0, -1, 0, 0,
	// hull 9
	(int16) 55000, -1,     0,  8, (int16) 35000, -1, 0, 0,
	(int16) 40000, -1, -2000, 10, 0, -1, 0, 0,
	// hull 10
	(int16) 60000, -1,     0,  4, -2000, 8, 0, 0,
	(int16) 40000, -1, -6000,  5, 0, -1, 0, 0,
	// hull 12
	0, -1,   150, 340, -150, 340, 0, -1,
	0, -1, 0, 0,
	// hull 13  == 164
	20000, -1,  4000,  7, 1000, 15, 0, 0,
	(int16) 35000, -1, -2000, 15, 0, -1, 0, 0,

	// hull misc = 180
	(int16) 44000, -1, -4400, 10, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 53000, -1, -5300, 10, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 63000, -1, -6300, 10, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 44000, -1, -1375, 32, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 53000, -1, -1656, 32, 0, -1, 0, 0,
	0, -1, 0, 0,

	// hull 11 == 240
	(int16) 63000, -1, -1968, 32, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 44000, -1, - 733, 60, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 53000, -1, - 883, 60, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 63000, -1, -1050, 60, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 44000, -1, - 488, 90, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 53000, -1, - 588, 90, 0, -1, 0, 0,
	0, -1, 0, 0,

	(int16) 63000, -1, - 700, 90, 0, -1, 0, 0,
	0, -1, 0, 0
};

static const uint16 freqmod_lengths[] = {
	0x1000, 0x1000, 0x20, 0x2000, 0x1000
};

static const uint16 freqmod_offsets[] = {
	0, 0x100, 0x200, 0x302, 0x202
};

static const int8 freqmod_table[0x502] = {
     0,   3,   6,   9,  12,  15,  18,  21,
    24,  27,  30,  33,  36,  39,  42,  45,
    48,  51,  54,  57,  59,  62,  65,  67,
    70,  73,  75,  78,  80,  82,  85,  87,
    89,  91,  94,  96,  98, 100, 102, 103,
   105, 107, 108, 110, 112, 113, 114, 116,
   117, 118, 119, 120, 121, 122, 123, 123,
   124, 125, 125, 126, 126, 126, 126, 126,
   126, 126, 126, 126, 126, 126, 125, 125,
   124, 123, 123, 122, 121, 120, 119, 118,
   117, 116, 114, 113, 112, 110, 108, 107,
   105, 103, 102, 100,  98,  96,  94,  91,
    89,  87,  85,  82,  80,  78,  75,  73,
    70,  67,  65,  62,  59,  57,  54,  51,
    48,  45,  42,  39,  36,  33,  30,  27,
    24,  21,  18,  15,  12,   9,   6,   3,
     0,  -3,  -6,  -9, -12, -15, -18, -21,
   -24, -27, -30, -33, -36, -39, -42, -45,
   -48, -51, -54, -57, -59, -62, -65, -67,
   -70, -73, -75, -78, -80, -82, -85, -87,
   -89, -91, -94, -96, -98,-100,-102,-103,
  -105,-107,-108,-110,-112,-113,-114,-116,
  -117,-118,-119,-120,-121,-122,-123,-123,
  -124,-125,-125,-126,-126,-126,-126,-126,
  -126,-126,-126,-126,-126,-126,-125,-125,
  -124,-123,-123,-122,-121,-120,-119,-118,
  -117,-116,-114,-113,-112,-110,-108,-107,
  -105,-103,-102,-100, -98, -96, -94, -91,
   -89, -87, -85, -82, -80, -78, -75, -73,
   -70, -67, -65, -62, -59, -57, -54, -51,
   -48, -45, -42, -39, -36, -33, -30, -27,
   -24, -21, -18, -15, -12,  -9,  -6,  -3,
  
     0,   1,   2,   3,   4,   5,   6,   7,
     8,   9,  10,  11,  12,  13,  14,  15,
    16,  17,  18,  19,  20,  21,  22,  23,
    24,  25,  26,  27,  28,  29,  30,  31,
    32,  33,  34,  35,  36,  37,  38,  39,
    40,  41,  42,  43,  44,  45,  46,  47,
    48,  49,  50,  51,  52,  53,  54,  55,
    56,  57,  58,  59,  60,  61,  62,  63,
    64,  65,  66,  67,  68,  69,  70,  71,
    72,  73,  74,  75,  76,  77,  78,  79,
    80,  81,  82,  83,  84,  85,  86,  87,
    88,  89,  90,  91,  92,  93,  94,  95,
    96,  97,  98,  99, 100, 101, 102, 103,
   104, 105, 106, 107, 108, 109, 110, 111,
   112, 113, 114, 115, 116, 117, 118, 119,
   120, 121, 122, 123, 124, 125, 126, 127,
  -128,-127,-126,-125,-124,-123,-122,-121,
  -120,-119,-118,-117,-116,-115,-114,-113,
  -112,-111,-110,-109,-108,-107,-106,-105,
  -104,-103,-102,-101,-100, -99, -98, -97,
   -96, -95, -94, -93, -92, -91, -90, -89,
   -88, -87, -86, -85, -84, -83, -82, -81,
   -80, -79, -78, -77, -76, -75, -74, -73,
   -72, -71, -70, -69, -68, -67, -66, -65,
   -64, -63, -62, -61, -60, -59, -58, -57,
   -56, -55, -54, -53, -52, -51, -50, -49,
   -48, -47, -46, -45, -44, -43, -42, -41,
   -40, -39, -38, -37, -36, -35, -34, -33,
   -32, -31, -30, -29, -28, -27, -26, -25,
   -24, -23, -22, -21, -20, -19, -18, -17,
   -16, -15, -14, -13, -12, -11, -10,  -9,
    -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1,
  
  -120, 120,
  
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
  -120,-120,-120,-120,-120,-120,-120,-120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,
   120, 120, 120, 120, 120, 120, 120, 120,

    41,  35, -66,-124, -31, 108, -42, -82,
    82,-112,  73, -15, -15, -69, -23, -21,
   -77, -90, -37,  60,-121,  12,  62,-103,
    36,  94,  13,  28,   6, -73,  71, -34,
   -77,  18,  77, -56,  67, -69,-117, -90,
    31,   3,  90, 125,   9,  56,  37,  31,
    93, -44, -53,  -4,-106, -11,  69,  59,
    19,  13,-119,  10,  28, -37, -82,  50,
    32,-102,  80, -18,  64, 120,  54,  -3,
    18,  73,  50, -10, -98, 125,  73, -36,
   -83,  79,  20, -14,  68,  64, 102, -48,
   107, -60,  48, -73,  50,  59, -95,  34,
   -10,  34,-111, -99, -31,-117,  31, -38,
   -80, -54,-103,   2, -71, 114, -99,  73,
    44,-128, 126, -59,-103, -43, -23,-128,
   -78, -22, -55, -52,  83, -65, 103, -42,
   -65,  20, -42, 126,  45, -36,-114, 102,
  -125, -17,  87,  73,  97,  -1, 105,-113,
    97, -51, -47,  30, -99,-100,  22, 114,
   114, -26,  29, -16,-124,  79,  74, 119,
     2, -41, -24,  57,  44,  83, -53, -55,
    18,  30,  51, 116, -98,  12, -12, -43,
   -44, -97, -44, -92,  89, 126,  53, -49,
    50,  34, -12, -52, -49, -45,-112,  45,
    72, -45,-113, 117, -26, -39,  29,  42,
   -27, -64,  -9,  43, 120,-127,-121,  68,
    14,  95,  80,   0, -44,  97,-115, -66,
   123,   5,  21,   7,  59,  51,-126,  31,
    24, 112,-110, -38, 100,  84, -50, -79,
  -123,  62, 105,  21,  -8,  70, 106,   4,
  -106, 115,  14, -39,  22,  47, 103, 104,
   -44,  -9,  74,  74, -48,  87, 104, 118,
};

static const uint16  spk_freq_table[12] = {
	36484, 34436, 32503, 30679, 29007, 27332, 
	25798, 24350, 22983, 21693,  20476, 19326
};

static const uint16 pcjr_freq_table[12] = {
	65472, 61760, 58304, 55040, 52032, 49024, 
	46272, 43648, 41216, 38912, 36736, 34624
};


////////////////////////////////////////
//
// V2 PC-Speaker MIDI driver
//
////////////////////////////////////////


Player_V2::Player_V2() {
	int i;

	// This simulates the pc speaker sound, which is driven
	// by the 8253 (square wave generator) and a low-band filter.

	sample_rate = g_system->property(OSystem::PROP_GET_SAMPLE_RATE, 0);
	ticks_per_sample = 1193000*1000 / sample_rate;
	last_freq = freq = 0;
	samples_left = 0;
	level = 0;
	decay = 0xF400; // 63455 // found by try and error
//	for (i = 0; (sample_rate << i) < 30000; i++)
//		decay = decay * decay / 65536;

	_mixer = g_mixer;
	_mixer->setupPremix(this, premix_proc);
	for (i = 0; i < 4; ++i) {
		clear_channel(i);
	}

	pcjr = 0;
	freqs_table = spk_freq_table;
	current_nr = next_nr = 0;
	current_data = next_data = 0;
	_next_tick = 0;
}

Player_V2::~Player_V2() {
	// Detach the premix callback handler
	_mixer->setupPremix (0, 0);
}

void Player_V2::chainNextSound() {
	int i;

	if (next_nr) {
		for (i = 0; i < 4; i++)
			clear_channel(i);
		current_nr = next_nr;
		current_data = next_data;
		for (i = 0; i < 4; i++) {
			channels[i].d.next_cmd = READ_LE_UINT16(next_data+6+2*i);
			if (channels[i].d.next_cmd)
				channels[i].d.time_left = 1;
			channels[i].d.music_script_nr = current_nr;
		}
		next_nr = 0;
		next_data = 0;
	}
}

void Player_V2::stopAllSounds() {
	for (int i = 0; i < 4; i++) {
		clear_channel(i);
	}
	next_nr = current_nr = 0;
	next_data = current_data = 0;
}

void Player_V2::stopSound(int nr) {
	if (next_nr == nr) {
		next_nr = 0;
		next_data = 0;
	}
	if (current_nr == nr) {
		for (int i = 0; i < 4; i++) {
			clear_channel(i);
		}
		current_nr = 0;
		current_data = 0;
		chainNextSound();
	}
}

void Player_V2::startSound(int nr, byte *data) {
	int cprio = current_data ? READ_LE_UINT16(current_data+4) : 0;
	int prio  = READ_LE_UINT16(data+4);
	int nprio = next_data ? READ_LE_UINT16(next_data+4) : 0;

	if (!current_nr || (cprio & 0xff) <= (prio & 0xff)) {
		int tnr = current_nr;
		int tprio = cprio;
		byte *tdata  = current_data;
		int i;
		for (i = 0; i < 4; i++)
			clear_channel(i);

		current_nr = nr;
		current_data = data;
		for (i = 0; i < 4; i++) {
			channels[i].d.next_cmd = READ_LE_UINT16(data+6+2*i);
			if (channels[i].d.next_cmd)
				channels[i].d.time_left = 1;
			channels[i].d.music_script_nr = current_nr;
		}
		nr   = tnr;
		prio = tprio;
		data = tdata;
	}
	
	if (!current_nr) {
		nr = 0;
		next_nr = 0;
		next_data = 0;
	}
	
	if (nr != current_nr
	    && (prio & 0xff00)
	    && (!next_nr
		|| (nprio & 0xff) <= (prio & 0xff))) {

		next_nr = nr;
		next_data = data;
	}
}

int Player_V2::getSoundStatus(int nr) {
	return current_nr == nr || next_nr == nr;
}


void Player_V2::premix_proc(void *param, int16 *buf, uint len) {
	((Player_V2 *) param)->do_mix(buf, len);
}

void Player_V2::clear_channel(int i) {
	ChannelInfo *channel = &channels[i];
	channel->d.time_left  = 0;
	channel->d.next_cmd   = 0;
	channel->d.base_freq  = 0;
	channel->d.freq_delta = 0;
	channel->d.freq = 0;
	channel->d.volume = 0;
	channel->d.volume_delta = 0;
	channel->d.inter_note_pause = 0;
	channel->d.transpose = 0;
	channel->d.hull_curve = 0;
	channel->d.hull_offset = 0;
	channel->d.hull_counter = 0;
	channel->d.freqmod_table = 0;
	channel->d.freqmod_offset = 0;
	channel->d.freqmod_incr = 0;
	channel->d.freqmod_multiplier = 0;
	channel->d.freqmod_modulo = 0;
}

void Player_V2::execute_cmd(ChannelInfo *channel) {
	uint16 value;
	int16 offset;
	uint8 *script_ptr;
	ChannelInfo * current_channel;
	ChannelInfo * dest_channel;

	current_channel = channel;

	if (channel->d.next_cmd == 0)
		return;
	script_ptr = &current_data[channel->d.next_cmd];

	for (;;) {
		uint8 opcode = *script_ptr++;
		if (opcode >= 0xf8) {
			switch (opcode) {
			case 0xf8: // set hull curve
				debug(9, "channels[%d]: hull curve %2d\n", 
				channel - channels, *script_ptr);
				channel->d.hull_curve = hull_offsets[*script_ptr/2];
				script_ptr++;
				break;

			case 0xf9: // set freqmod curve
				debug(9, "channels[%d]: freqmod curve %2d\n", 
				channel - channels, *script_ptr);
				channel->d.freqmod_table = freqmod_offsets[*script_ptr/4];
				channel->d.freqmod_modulo = freqmod_lengths[*script_ptr/4];
				script_ptr++;
				break;

			case 0xfd: // clear other channel
				value = READ_LE_UINT16 (script_ptr);
				debug(9, "clear channel %d\n", value/50);
				script_ptr += 2;
				channel = &channels[value / sizeof(ChannelInfo)];
				// fall through

			case 0xfa: // clear current channel
				if (opcode == 0xfa)
					debug(9, "clear channel\n");
				channel->d.next_cmd   = 0;
				channel->d.base_freq  = 0;
				channel->d.freq_delta = 0;
				channel->d.freq = 0;
				channel->d.volume = 0;
				channel->d.volume_delta = 0;
				channel->d.inter_note_pause = 0;
				channel->d.transpose = 0;
				channel->d.hull_curve = 0;
				channel->d.hull_offset = 0;
				channel->d.hull_counter = 0;
				channel->d.freqmod_table = 0;
				channel->d.freqmod_offset = 0;
				channel->d.freqmod_incr = 0;
				channel->d.freqmod_multiplier = 0;
				channel->d.freqmod_modulo = 0;
				break;

			case 0xfb: // ret from subroutine
				debug(9, "ret from sub\n");
				script_ptr = retaddr;
				break;

			case 0xfc: // call subroutine
				offset = READ_LE_UINT16 (script_ptr);
				debug(9, "subroutine %d\n", offset);
				script_ptr += 2;
				retaddr = script_ptr;
				script_ptr = current_data + offset;
				debug(9, "XXX1: %p -> %04x", script_ptr, offset);
				break;

			case 0xfe: // loop music
				opcode = *script_ptr++;
				offset = READ_LE_UINT16 (script_ptr);
				script_ptr += 2;
				debug(9, "loop if %d to %d\n", opcode, offset);
				if (!channel->array[opcode/2] || --channel->array[opcode/2])
					script_ptr += offset;
				break;

			case 0xff: // set parameter
				opcode = *script_ptr++;
				value = READ_LE_UINT16 (script_ptr);
				channel->array[opcode/2] = value;
				debug(9, "channels[%d]: set param %2d = %5d\n", 
				channel - &channels[0], opcode, value);
				script_ptr+=2;
				if (opcode == 0)
					goto end;
				break;
			}
		} else { // opcode < 0xf8
			for (;;) {
				int16 note, octave;
				dest_channel = &channels[opcode >> 5];
				channel->d.time_left = channel->d.tempo * note_lengths[opcode & 0x1f];
				debug(9, "channels[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s\n", 
				      opcode>>5, script_ptr ? script_ptr - current_data : 0,
				      *script_ptr & 0x7f, (signed short) dest_channel->d.transpose, opcode & 0x1f,
				      dest_channel->d.hull_curve, dest_channel->d.freqmod_table,
				      dest_channel->d.freqmod_incr,dest_channel->d.freqmod_multiplier,
				      *script_ptr & 0x80 ? "last":"");
				opcode = *script_ptr++;
				note = opcode & 0x7f;
				if (note != 0x7f) {
					uint16 freq;
					dest_channel->d.time_left = channel->d.time_left;
					dest_channel->d.note_length = 
					channel->d.time_left - dest_channel->d.inter_note_pause;
					note += dest_channel->d.transpose;
					while (note < 0)
						note += 12;
					octave = note / 12;
					note = note % 12;
					dest_channel->d.hull_offset = 0;
					dest_channel->d.hull_counter = 1;
					if (pcjr && dest_channel == &channels[3]) {
						dest_channel->d.hull_curve = 180 + note * 12;
						freq = 384 - 64 * octave;
					} else {
						freq = freqs_table[note] >> octave;
					}
					dest_channel->d.freq = dest_channel->d.base_freq = freq;
				}
				if ((opcode & 0x80) != 0)
					goto end;
				opcode = *script_ptr++;
			}
		}
	}

end:
	channel = current_channel;
	if (channel->d.time_left)
		goto finish;

	channel->d.next_cmd = 0;
	int i;
	for (i = 0; i< 4; i++) {
		if (channels[i].d.time_left)
			goto finish;
	}

	current_nr = 0;
	current_data = 0;
	chainNextSound();
	return;

finish:
	channel->d.next_cmd = script_ptr - current_data;
	return;
}

void Player_V2::next_freqs(ChannelInfo *channel) {
	channel->d.volume    += channel->d.volume_delta;
	channel->d.base_freq += channel->d.freq_delta;

	channel->d.freqmod_offset += channel->d.freqmod_incr;
	if (channel->d.freqmod_offset > channel->d.freqmod_modulo)
		channel->d.freqmod_offset -= channel->d.freqmod_modulo;
	channel->d.freq = 
		(int) (freqmod_table[channel->d.freqmod_table + (channel->d.freqmod_offset >> 4)])
		* (int) channel->d.freqmod_multiplier / 256
		+ channel->d.base_freq;

#if 0
	debug(9, "Freq: %d/%d, %d/%d/%d*%d %d\n",
	      channel->d.base_freq, (int16)channel->d.freq_delta,
	      channel->d.freqmod_table, channel->d.freqmod_offset,
	      channel->d.freqmod_incr, channel->d.freqmod_multiplier,
	      channel->d.freq);
#endif

	if (channel->d.note_length && !--channel->d.note_length) {
		channel->d.hull_offset += 16;
		channel->d.hull_counter = 1;
	}

	if (!--channel->d.time_left) {
		execute_cmd(channel);
	}

#if 0
	debug(9, "channels[%d]: freq %d hull %d/%d/%d\n", 
	      channel - &channels[0], channel->d.freq,
	      channel->d.hull_curve, channel->d.hull_offset,
	      channel->d.hull_counter);
#endif

	if (channel->d.hull_counter && !--channel->d.hull_counter) {
		for (;;) {
			const int16 *hull_ptr = hulls
			+ channel->d.hull_curve + channel->d.hull_offset/2;
			if (hull_ptr[1] == -1) {
				channel->d.volume = hull_ptr[0];
				if (hull_ptr[0] == 0)
				channel->d.volume_delta = 0;
				channel->d.hull_offset += 4;
			} else {
				channel->d.volume_delta = hull_ptr[0];
				channel->d.hull_counter = hull_ptr[1];
				channel->d.hull_offset += 4;
				break;
			}
		}
	}
}

void Player_V2::do_mix (int16 *data, int len) {
	int step;

	do {
		step = len;
		if (step > _next_tick)
			step = _next_tick;
		generate_samples(data, step);

		if (!(_next_tick -= step)) {
//			if (_timer_proc)
//				(*_timer_proc) (_timer_param);
			for (int i = 0; i < 4; i++) {
				if (!channels[i].d.time_left)
					continue;
				next_freqs(&channels[i]);
			}
			_next_tick = 93;
		}
		data += step;
	} while (len -= step);
}

void Player_V2::generate_samples(int16 *data, int step) {
	int winning_channel = -1;
	int i, j;
	for (j = 0; j < step; j++) {
		if ((samples_left -= FREQ_HZ) < 0) {
			for (i = 0; i < 4; i++) {
//				if (!channels[i].d.time_left)
//					continue;
//				next_freqs(&channels[i]);
				if (winning_channel == -1
				    && channels[i].d.volume
				    && channels[i].d.time_left) {
					winning_channel = i;
				}
			}
			if (winning_channel != -1) {
				freq = channels[winning_channel].d.freq;
			} else {
				freq = 0;
				if (!last_freq) {
					memset (data, 0, step);
					return;
				}
			}
			samples_left = sample_rate;
		}
	
		level = (level * decay) >> 16;
		if (ticks_counted < freq*500)
			level += 0xffff - decay;

		data[j] = (level >> 1);
		
		ticks_counted += ticks_per_sample;
		if (ticks_counted >= last_freq*1000) {
			ticks_counted -= last_freq*1000;
			last_freq = freq;
		}
	}
}


Index: module.mk
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/module.mk,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- module.mk	22 May 2003 16:23:05 -0000	1.14
+++ module.mk	26 May 2003 22:03:02 -0000	1.15
@@ -16,6 +16,7 @@
 	scumm/instrument.o \
 	scumm/nut_renderer.o \
 	scumm/object.o \
+	scumm/player_v2.o\
 	scumm/resource.o \
 	scumm/resource_v2.o \
 	scumm/resource_v3.o \

Index: scumm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.h,v
retrieving revision 1.215
retrieving revision 1.216
diff -u -d -r1.215 -r1.216
--- scumm.h	26 May 2003 13:14:57 -0000	1.215
+++ scumm.h	26 May 2003 22:03:02 -0000	1.216
@@ -40,6 +40,7 @@
 class Scumm;
 class IMuse;
 class IMuseDigital;
+class Player_V2;
 class Actor;
 class Sound;
 class Bundle;
@@ -268,6 +269,7 @@
 	 * on some architectures. */
 	IMuse *_imuse;
 	IMuseDigital *_imuseDigital;
+	Player_V2 *_playerV2;
 	uint32 _features;
 	VerbSlot *_verbs;
 	ObjectData *_objs;

Index: scummvm.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scummvm.cpp,v
retrieving revision 2.181
retrieving revision 2.182
diff -u -d -r2.181 -r2.182
--- scummvm.cpp	26 May 2003 13:14:57 -0000	2.181
+++ scummvm.cpp	26 May 2003 22:03:03 -0000	2.182
@@ -31,6 +31,7 @@
 #include "imuse_digi.h"
 #include "intern.h"
 #include "object.h"
+#include "player_v2.h"
 #include "resource.h"
 #include "sound.h"
 #include "string.h"
@@ -609,7 +610,14 @@
 	if (_features & GF_AFTER_V7) {
 		_imuseDigital = new IMuseDigital(this);
 		_imuse = NULL;
+		_playerV2 = NULL;
+	} else if (_features & GF_OLD_BUNDLE && !(_features & GF_AFTER_V3)) {
+		debug (0, "Creating player");
+		_playerV2 = new Player_V2();
+		_imuse = NULL;
+		_imuseDigital = NULL;
 	} else {
+		_playerV2 = NULL;
 		_imuseDigital = NULL;
 		_imuse = IMuse::create (syst, detector->createMidi());
 		if (_imuse) {
@@ -650,6 +658,7 @@
 	delete _sound;
 	delete _imuse;
 	delete _imuseDigital;
+	delete _playerV2;
 	delete _languageBuffer;
 	delete _audioNames;
 

Index: sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/sound.cpp,v
retrieving revision 1.126
retrieving revision 1.127
diff -u -d -r1.126 -r1.127
--- sound.cpp	25 May 2003 00:30:48 -0000	1.126
+++ sound.cpp	26 May 2003 22:03:04 -0000	1.127
@@ -26,6 +26,7 @@
 #include "sound/mididrv.h"
 #include "imuse.h"
 #include "imuse_digi.h"
+#include "player_v2.h"
 #include "actor.h"
 #include "bundle.h"
 #include "common/config-file.h"
@@ -389,8 +390,11 @@
 	
 	}
 	
-	if (_scumm->_features & GF_OLD_BUNDLE)
-		return;	// FIXME
+	if (_scumm->_features & GF_OLD_BUNDLE) {
+		if (_scumm->_playerV2)
+			_scumm->_playerV2->startSound (soundID, ptr);
+		return;
+	}
 
 	if (_scumm->_gameId == GID_MONKEY_VGA || _scumm->_gameId == GID_MONKEY_EGA) {
 		// FIXME: This evil hack works around the fact that in some
@@ -611,6 +615,9 @@
 	if (_scumm->_imuse)
 		return _scumm->_imuse->getSoundStatus(sound);
 
+	if (_scumm->_playerV2)
+		return _scumm->_playerV2->getSoundStatus (sound);
+
 	return 0;
 }
 
@@ -677,6 +684,8 @@
 		_scumm->_imuseDigital->stopSound(a);
 	} else if (_scumm->_imuse) {
 		_scumm->_imuse->stopSound(a);
+	} else if (_scumm->_playerV2) {
+		_scumm->_playerV2->stopSound (a);
 	}
 
 	for (i = 0; i < 10; i++)
@@ -693,7 +702,10 @@
 	if (_scumm->_imuse) {
 		_scumm->_imuse->stop_all_sounds();
 		_scumm->_imuse->clear_queue();
+	} else if (_scumm->_playerV2) {
+		_scumm->_playerV2->stopAllSounds();
 	}
+
 	clearSoundQue();
 	stopSfxSound();
 }





More information about the Scummvm-git-logs mailing list