aboutsummaryrefslogtreecommitdiff
path: root/sword1/music.cpp
blob: ca449d9cd8f5a5973c96c6fbdebf839265780ab9 (plain)
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
129
/* ScummVM - Scumm Interpreter
 * Copyright (C) 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$
 *
 */

// todo: add fadeout, crossfading.
// this code always loops. make it depend on _loopFlag

#include "stdafx.h"
#include "music.h"
#include "sound/mixer.h"
#include "common/util.h"
#include "common/file.h"

SwordMusic::SwordMusic(OSystem *system, SoundMixer *pMixer) {
	_system = system;
	_mixer = pMixer;
	_mixer->setupPremix(passMixerFunc, this);
	_fading = 0;
	_playing = false;
	_loop = false;
	_mutex = _system->create_mutex();
	_waveSize = _wavePos = _bufPos = _smpInBuf = 0;
	assert(_mixer->getOutputRate() == 22050);
}

void SwordMusic::passMixerFunc(void *param, int16 *buf, uint len) {
	((SwordMusic*)param)->mixer(buf, len);
}

void SwordMusic::mixer(int16 *buf, uint len) {
	if (!_playing)
		memset(buf, 0, 2 * len * sizeof(int16));
	else {
		_system->lock_mutex(_mutex);
		len >>= 1;
		if (len > _smpInBuf)
			warning("SwordMusic::mixer: sample buffer underrun");
		else {
			uint32 maxLen = BUFSIZE - _bufPos;
			if (len >= maxLen) {
				for (uint32 cnt = 0; cnt < maxLen; cnt++)
					buf[(cnt << 2) | 0] = buf[(cnt << 2) | 1] =
					buf[(cnt << 2) | 2] = buf[(cnt << 2) | 3] = _musicBuf[_bufPos + cnt];
				_smpInBuf -= maxLen;
				_bufPos = 0;
				len -= maxLen;
				buf += maxLen * 4;
			}
			if (len) {
				for (uint32 cnt = 0; cnt < len; cnt++)
					buf[(cnt << 2) | 0] = buf[(cnt << 2) | 1] =
					buf[(cnt << 2) | 2] = buf[(cnt << 2) | 3] = _musicBuf[_bufPos + cnt];
				_smpInBuf -= len;
				_bufPos += len;
			}
		}
		_system->unlock_mutex(_mutex);
	}
}

void SwordMusic::stream(void) {
	// make sure we've got enough samples in buffer.
	if ((_smpInBuf < SAMPLERATE) && _playing) {
		_system->lock_mutex(_mutex);
		uint32 loadTotal = BUFSIZE - _smpInBuf;
		while (uint32 doLoad = loadTotal) {
			if (BUFSIZE - ((_bufPos + _smpInBuf) % BUFSIZE) < loadTotal)
				doLoad = BUFSIZE - (_bufPos + _smpInBuf) % BUFSIZE;
			if (_waveSize - _wavePos < doLoad)
				doLoad = _waveSize - _wavePos;
			int16 *dest = _musicBuf + ((_bufPos + _smpInBuf) % BUFSIZE);
			_musicFile.read(dest, doLoad * 2);
			_wavePos += doLoad;
			if (_wavePos == _waveSize) {
				_wavePos = 0;
				_musicFile.seek(WAVEHEADERSIZE);
			}
			loadTotal -= doLoad;
			_smpInBuf += doLoad;
		}
		_system->unlock_mutex(_mutex);
	}
}

void SwordMusic::startMusic(int32 tuneId, int32 loopFlag) {
	_system->lock_mutex(_mutex);
	_loop = (loopFlag > 0);
	if (tuneId) {
		if (_musicFile.isOpen())
			_musicFile.close();
		char fName[20];
		sprintf(fName, "MUSIC\\%s.wav", _tuneList[tuneId]);
		_musicFile.open(fName);
		if (_musicFile.isOpen()) {
			_musicFile.seek(0x28);
			_waveSize = _musicFile.readUint32LE() / 2;
			_wavePos = 0;
			_smpInBuf = 0;
			_bufPos = 0;
			_playing = true;
		} else
			_playing = false;
	} else
		_playing = false;
	_system->unlock_mutex(_mutex);
	stream();
}

void SwordMusic::fadeDown(void) {
	warning("stub: SwordMusic::fadeDown");
}