8bitworkshop/presets/cpc/music.c

105 lines
9.9 KiB
C

/*
Demonstrates playing multi-voice music on the PSG
using the CPC BIOS functions.
Similar to the music example in "Making Arcade Games in C".
*/
#include <stdlib.h>
#include <string.h>
#include "cpctelera.h"
#include "sound_bios.h"
//#link "sound_bios.c"
#include "music.h"
typedef unsigned char byte;
typedef unsigned short word;
//
// MUSIC ROUTINES
//
void music_start(const byte* music);
void music_update();
// Namespace(length=64, upper=49, freq=62500.0, bias=0, maxbits=12)
// 430.0 4.526547151857908 49
const int note_table[64] = {
2464,2326,2195,2072,1956,1846,1742,1644,1552,1465,1383,1305,1232,1163,1098,1036,978,923,871,822,776,733,691,653,616,581,549,518,489,461,436,411,388,366,346,326,308,291,274,259,244,231,218,206,194,183,173,163,154,145,137,129,122,115,109,103,97,92,86,82,77,73,69,65,};
struct {
byte volume;
} voice[3];
byte music_index = 0;
byte cur_duration = 0;
byte num_voices = 3;
static const byte* music_ptr = NULL;
inline byte next_music_byte() {
return *music_ptr++;
}
void music_update() {
byte ch;
byte freech = 0;
for (ch=0; ch<num_voices; ch++) {
if (voice[ch].volume) {
voice[ch].volume--;
} else {
freech = ch;
}
}
if (music_ptr) {
ch = freech;
while (cur_duration == 0) {
byte note = next_music_byte();
if ((note & 0x80) == 0) {
int period = note_table[note & 63];
sound(ch+1, period, 5, 15, 1, 0, 0);
voice[ch].volume = 31;
ch = ch ? ch-1 : num_voices-1;
} else {
if (note == 0xff)
music_ptr = NULL;
cur_duration = note & 63;
}
}
cur_duration--;
}
}
void music_start(const byte* music) __critical {
music_ptr = music;
cur_duration == 0;
}
///
/// MUSIC TEST
///
#ifdef __MAIN__
const byte music1[] = {
0x38,0x8c,0x3a,0x88,0x20,0x81,0x23,0x82,0x28,0x81,0x3b,0x32,0x2c,0xa4,0x3a,0x8c,0x38,0x32,0x2c,0x91,0x1f,0x83,0x22,0x83,0x27,0x81,0x37,0x31,0x2e,0xa4,0x35,0x2c,0x8c,0x37,0x31,0x2e,0x90,0x20,0x83,0x23,0x83,0x27,0x82,0x38,0x2f,0x27,0xbf,0x85,0x20,0x81,0x23,0x82,0x27,0x81,0x38,0x2f,0x27,0xb0,0x2c,0x2c,0x20,0x98,0x2f,0x2c,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x8c,0x31,0x2e,0x27,0x98,0x33,0x2f,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x34,0x31,0x20,0x8c,0x33,0x2f,0x27,0x98,0x31,0x2e,0x2a,0x8c,0x1e,0x8c,0x22,0x8c,0x1e,0x8c,0x2e,0x2a,0x25,0x98,0x2a,0x2a,0x2a,0x8c,0x1e,0x8c,0x22,0x8c,0x2c,0x2c,0x29,0x8c,0x2e,0x2e,0x28,0x98,0x2f,0x2c,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x8c,0x2c,0x27,0x23,0x98,0x2c,0x26,0x23,0x8c,0x1c,0x8c,0x23,0x8c,0x2b,0x22,0x20,0x8c,0x2c,0x26,0x20,0x98,0x2e,0x27,0x1f,0x8c,0x1b,0x8c,0x1f,0x8c,0x1b,0x8c,0x22,0x8c,0x1f,0x8c,0x27,0x27,0x1f,0x8c,0x22,0x8c,0x2b,0x98,0x2c,0x2c,0x20,0x98,0x2f,0x2c,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x8c,0x31,0x2e,0x27,0x98,0x33,0x2f,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x34,0x31,0x20,0x8c,0x33,0x2f,0x27,0x98,0x31,0x2e,0x2a,0x8c,0x1e,0x8c,0x22,0x8c,0x1e,0x8c,0x2e,0x2a,0x25,0x98,0x2a,0x2a,0x2a,0x8c,0x1e,0x8c,0x22,0x8c,0x2c,0x2c,0x29,0x8c,0x2e,0x2e,0x28,0x98,0x2f,0x2c,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x2e,0x25,0x20,0x8c,0x2c,0x27,0x23,0x98,0x2b,0x27,0x22,0x8c,0x1b,0x8c,0x22,0x8c,0x29,0x20,0x1f,0x8c,0x2b,0x27,0x22,0x98,0x2c,0x27,0x23,0x8c,0x1b,0x8c,0x20,0x8c,0x1b,0x8c,0x27,0x8c,0x23,0x8c,0x2c,0x27,0x23,0x8c,0x1b,0x8c,0x20,0x8c,0x22,0x8c,0x23,0x8c,0x27,0x8c,0x36,0x33,0x2a,0x8c,0x23,0x8c,0x2a,0x8c,0x27,0x8c,0x1e,0x8c,0x23,0x8c,0x36,0x33,0x2a,0x8c,0x27,0x8c,0x2a,0x8c,0x35,0x31,0x27,0x8c,0x33,0x2f,0x2a,0x8c,0x23,0x8c,0x31,0x2e,0x2a,0x8c,0x22,0x8c,0x2a,0x8c,0x25,0x8c,0x2e,0x2a,0x25,0x8c,0x22,0x8c,0x2a,0x2a,0x2a,0x8c,0x25,0x8c,0x2a,0x8c,0x2c,0x2c,0x29,0x8c,0x2e,0x2e,0x28,0x8c,0x22,0x8c,0x2f,0x2c,0x27,0x8c,0x23,0x8c,0x27,0x8c,0x23,0x8c,0x2c,0x27,0x23,0x8c,0x23,0x8c,0x2c,0x26,0x23,0x8c,0x23,0x8c,0x28,0x8c,0x2b,0x22,0x23,0x8c,0x2c,0x26,0x20,0x8c,0x23,0x8c,0x2e,0x27,0x1f,0x8c,0x1f,0x8c,0x22,0x8c,0x27,0x8c,0x2b,0x27,0x22,0x8c,0x1f,0x8c,0x27,0x27,0x27,0x8c,0x22,0x8c,0x27,0x8c,0x2b,0x8c,0x27,0x8c,0x22,0x8c,0x36,0x33,0x2a,0x8c,0x23,0x8c,0x27,0x8c,0x2a,0x8c,0x23,0x8c,0x27,0x8c,0x36,0x33,0x2a,0x8c,0x23,0x8c,0x27,0x8c,0x35,0x31,0x2a,0x8c,0x33,0x2f,0x2a,0x8c,0x27,0x8c,0x31,0x2e,0x2a,0x8c,0x22,0x8c,0x25,0x8c,0x2a,0x8c,0x2e,0x2a,0x25,0x8c,0x25,0x8c,0x2a,0x2a,0x2a,0x8c,0x22,0x8c,0x25,0x8c,0x2c,0x2c,0x29,0x8c,0x2e,0x2e,0x28,0x8c,0x22,0x8c,0x2f,0x2c,0x27,0x8c,0x23,0x8c,0x27,0x8c,0x2e,0x25,0x20,0x8c,0x2c,0x27,0x23,0x8c,0x23,0x8c,0x2b,0x27,0x22,0x8c,0x22,0x8c,0x27,0x8c,0x29,0x20,0x2b,0x8c,0x2b,0x27,0x22,0x8c,0x22,0x8c,0x2c,0x27,0x23,0x8c,0x23,0x8c,0x28,0x25,0x25,0x8c,0x20,0x8c,0x25,0x22,0x28,0x8c,0x25,0x8c,0x2c,0x27,0x23,0xb0,0x38,0x8c,0x3a,0x88,0x20,0x81,0x23,0x82,0x28,0x81,0x3b,0x32,0x2c,0xa4,0x3a,0x8c,0x38,0x32,0x2c,0x91,0x1f,0x83,0x22,0x83,0x27,0x81,0x37,0x31,0x2e,0xa4,0x35,0x2c,0x8c,0x37,0x31,0x2e,0x90,0x20,0x83,0x23,0x83,0x27,0x82,0x38,0x2f,0x27,0xbf,0x85,0x20,0x81,0x23,0x82,0x27,0x81,0x38,0x2f,0x27,0xb0,0x20,0x98,0x23,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x8c,0x25,0x27,0x98,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x28,0x20,0x8c,0x27,0x27,0x98,0x25,0x8c,0x1e,0x8c,0x22,0x8c,0x1e,0x8c,0x22,0x25,0x98,0x1e,0x8c,0x1e,0x8c,0x22,0x8c,0x20,0x1e,0x8c,0x22,0x25,0x98,0x23,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x8c,0x20,0x27,0x98,0x20,0x8c,0x1c,0x8c,0x23,0x8c,0x1f,0x20,0x8c,0x20,0x28,0x98,0x22,0x8c,0x1b,0x8c,0x1f,0x8c,0x1b,0x8c,0x22,0x8c,0x1f,0x8c,0x1b,0x27,0x8c,0x22,0x8c,0x2b,0x98,0x20,0x98,0x23,0x20,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x8c,0x25,0x27,0x98,0x27,0x8c,0x1b,0x8c,0x23,0x8c,0x28,0x20,0x8c,0x27,0x27,0x98,0x25,0x8c,0x1e,0x8c,0x22,0x8c,0x1e,0x8c,0x22,0x25,0x98,0x1e,0x8c,0x1e,0x8c,0x22,0x8c,0x20,0x1e,0x8c,0x22,0x25,0x98,0x23,0x8c,0x1b,0x8c,0x23,0x8c,0x22,0x20,0x8c,0x20,0x27,0x98,0x1f,0x8c,0x1b,0x8c,0x22,0x8c,0x1d,0x1f,0x8c,0x1f,0x27,0x98,0x20,0x8c,0x1b,0x8c,0x20,0x8c,0x1b,0x8c,0x27,0x8c,0x23,0x8c,0x20,0x20,0x8c,0x1b,0x8c,0x20,0x8c,0x22,0x8c,0x23,0x8c,0x27,0x8c,0x27,0x2a,0x20,0x8c,0x23,0x8c,0x2a,0x8c,0x27,0x8c,0x1e,0x8c,0x23,0x8c,0x27,0x2a,0x1e,0x8c,0x27,0x8c,0x2a,0x8c,0x29,0x25,0x27,0x8c,0x23,0x27,0x1e,0x8c,0x23,0x8c,0x25,0x22,0x1e,0x8c,0x22,0x8c,0x2a,0x8c,0x25,0x8c,0x22,0x1e,0x1e,0x8c,0x22,0x8c,0x1e,0x1e,0x8c,0x25,0x8c,0x2a,0x8c,0x20,0x25,0x8c,0x22,0x1f,0x8c,0x22,0x8c,0x23,0x20,0x8c,0x23,0x8c,0x27,0x8c,0x23,0x8c,0x20,0x20,0x8c,0x23,0x8c,0x20,0x1c,0x8c,0x23,0x8c,0x28,0x8c,0x1f,0x23,0x8c,0x20,0x20,0x8c,0x23,0x8c,0x22,0x1b,0x8c,0x1f,0x8c,0x22,0x8c,0x27,0x8c,0x1f,0x22,0x8c,0x1f,0x8c,0x1b,0x1f,0x8c,0x22,0x8c,0x27,0x8c,0x2b,0x8c,0x27,0x8c,0x22,0x8c,0x2a,0x27,0x1e,0x8c,0x23,0x8c,0x27,0x8c,0x2a,0x8c,0x23,0x8c,0x27,0x8c,0x27,0x2a,0x1e,0x8c,0x23,0x8c,0x27,0x8c,0x29,0x25,0x2a,0x8c,0x27,0x23,0x23,0x8c,0x27,0x8c,0x25,0x22,0x1e,0x8c,0x22,0x8c,0x25,0x8c,0x2a,0x8c,0x22,0x1e,0x22,0x8c,0x25,0x8c,0x1e,0x1e,0x8c,0x22,0x8c,0x25,0x8c,0x20,0x2a,0x8c,0x22,0x1f,0x8c,0x22,0x8c,0x23,0x20,0x8c,0x23,0x8c,0x27,0x8c,0x22,0x20,0x8c,0x20,0x2c,0x8c,0x23,0x8c,0x1f,0x1b,0x8c,0x22,0x8c,0x27,0x8c,0x1d,0x2b,0x8c,0x1f,0x1f,0x8c,0x22,0x8c,0x20,0x1b,0x8c,0x23,0x8c,0x25,0x8c,0x20,0x8c,0x28,0x8c,0x25,0x8c,0x20,0x27,0xb0,0x38,0x8c,0x3a,0x88,0x20,0x81,0x23,0x82,0x28,0x81,0x3b,0x32,0x2c,0xa4,0x3a,0x8c,0x38,0x32,0x2c,0x91,0x1f,0x83,0x22,0x83,0x27,0x81,0x37,0x31,0x2e,0xa4,0x35,0x2c,0x8c,0x37,0x31,0x2e,0x90,0x20,0x83,0x23,0x83,0x27,0x82,0x38,0x2f,0x27,0xbf,0x85,0x20,0x81,0x23,0x82,0x27,0x81,0x38,0x27,0x2f,0x81,0x2f,0xaf,0x2c,0x82,0x2c,0x96,0x33,0x2c,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x87,0x2e,0x85,0x27,0x97,0x2f,0x8d,0x1b,0x8c,0x23,0x8a,0x31,0x82,0x20,0x8b,0x2f,0x33,0x81,0x27,0x97,0x2e,0x36,0x8d,0x1e,0x8c,0x22,0x8c,0x1e,0x8a,0x2a,0x81,0x31,0x81,0x25,0x97,0x25,0x83,0x36,0x8a,0x1e,0x8c,0x22,0x8a,0x2c,0x82,0x35,0x1e,0x8c,0x34,0x25,0x81,0x2e,0x97,0x33,0x82,0x2c,0x8a,0x1b,0x8c,0x23,0x8c,0x20,0x88,0x2f,0x27,0x84,0x27,0x95,0x26,0x81,0x2f,0x8e,0x1c,0x8c,0x23,0x89,0x2e,0x83,0x20,0x88,0x26,0x82,0x2c,0x82,0x28,0x97,0x27,0x81,0x2b,0x8c,0x1b,0x8c,0x1f,0x8c,0x1b,0x8c,0x22,0x8c,0x1f,0x8b,0x22,0x81,0x27,0x8c,0x22,0x8c,0x2b,0x97,0x2c,0x2c,0x99,0x2c,0x33,0x20,0x8c,0x1b,0x8c,0x23,0x8c,0x20,0x88,0x2e,0x84,0x27,0x94,0x2f,0x90,0x1b,0x8c,0x23,0x8b,0x31,0x81,0x20,0x8b,0x2f,0x33,0x81,0x27,0x95,0x2e,0x81,0x36,0x8e,0x1e,0x8c,0x22,0x8c,0x1e,0x88,0x31,0x82,0x2a,0x82,0x25,0x97,0x36,0x81,0x2a,0x8c,0x1e,0x8c,0x22,0x8b,0x2c,0x35,0x81,0x1e,0x8c,0x2e,0x25,0x81,0x34,0x97,0x2c,0x81,0x33,0x8b,0x1b,0x8c,0x23,0x8b,0x31,0x81,0x20,0x8a,0x27,0x82,0x2f,0x27,0x97,0x2e,0x81,0x27,0x8c,0x1b,0x8c,0x22,0x8b,0x2c,0x81,0x1f,0x8a,0x27,0x82,0x2e,0x27,0x97,0x27,0x82,0x2f,0x8b,0x1b,0x8c,0x20,0x8c,0x1b,0x8c,0x27,0x8c,0x23,0x8b,0x2f,0x81,0x20,0x81,0x27,0x8b,0x1b,0x8c,0x20,0x8c,0x22,0x8c,0x23,0x8c,0x27,0x8c,0x20,0x8c,0x27,0x23,0x8c,0x2a,0x2a,0x8c,0x2f,0x27,0x8c,0x33,0x1e,0x8c,0x23,0x8c,0x1e,0x8c,0x27,0x27,0x8c,0x2a,0x23,0x8c,0x2f,0x25,0x8c,0x33,0x27,0x8c,0x29,0x8c,0x1e,0x8c,0x25,0x22,0x8c,0x2a,0x2a,0x8c,0x2e,0x25,0x8c,0x31,0x1e,0x8c,0x22,0x8c,0x1e,0x8c,0x25,0x25,0x8c,0x2a,0x2a,0x8c,0x2e,0x25,0x8c,0x31,0x1f,0x8c,0x22,0x8c,0x20,0x8c,0x23,0x23,0x8c,0x27,0x27,0x8c,0x2c,0x23,0x8c,0x2f,0x20,0x8c,0x23,0x8c,0x1c,0x8c,0x23,0x23,0x8c,0x28,0x28,0x8c,0x2c,0x23,0x8c,0x2f,0x20,0x8c,0x23,0x8c,0x1b,0x8c,0x22,0x1f,0x8c,0x27,0x22,0x8c,0x2b,0x27,0x8c,0x2e,0x22,0x8c,0x1f,0x8c,0x1f,0x8c,0x27,0x22,0x8c,0x2b,0x27,0x8c,0x2e,0x2b,0x8c,0x33,0x27,0x8c,0x22,0x8c,0x1e,0x8c,0x27,0x23,0x8c,0x2a,0x27,0x8c,0x2f,0x2a,0x8c,0x33,0x23,0x8c,0x27,0x8c,0x1e,0x8c,0x27,0x27,0x8c,0x2a,0x23,0x8c,0x2f,0x25,0x8c,0x33,0x27,0x8c,0x29,0x8c,0x1e,0x8c,0x25,0x22,0x8c,0x2a,0x25,0x8c,0x2e,0x2a,0x8c,0x31,0x22,0x8c,0x25,0x8c,0x1e,0x8c,0x25,0x22,0x8c,0x2a,0x25,0x8c,0x2e,0x2a,0x8c,0x2e,0x1f,0x8c,0x22,0x8c,0x2f,0x20,0x8c,0x23,0x8c,0x27,0x8c,0x2e,0x20,0x8c,0x2c,0x2c,0x8c,0x23,0x8c,0x2b,0x1b,0x8c,0x22,0x8c,0x27,0x8c,0x29,0x2b,0x8c,0x2b,0x1f,0x8c,0x22,0x8c,0x2c,0x1b,0x8c,0x23,0x8c,0x25,0x8c,0x20,0x8c,0x28,0x8c,0x25,0x8c,0x2c,0x27,0xb0,0x38,0x2c,0x8c,0x3a,0x2e,0x88,0x20,0x81,0x23,0x82,0x28,0x81,0x3b,0x2f,0x2c,0xa4,0x3a,0x2e,0x8c,0x38,0x2c,0x91,0x1f,0x83,0x22,0x83,0x27,0x81,0x37,0x2b,0x2b,0xa4,0x35,0x29,0x8c,0x37,0x2b,0x90,0x20,0x83,0x23,0x83,0x27,0x82,0x38,0x2c,0x2c,0xbf,0x85,0x20,0x81,0x23,0x82,0x27,0x81,0x38,0x2c,0x2f,0xff
};
void delay(int n) {
while (n--) cpct_waitVSYNC();
}
void main(void) {
env(1, 25, 15, 1);
while (1) {
if (!music_ptr) music_start(music1);
music_update();
delay(6);
}
}
#endif