summaryrefslogtreecommitdiff
path: root/audio.c
blob: 88af3a3eb654ad93ed852142d9506f5a1d666119 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright 2008-2010  Segher Boessenkool  <segher@kernel.crashing.org>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt

#include <stdio.h>
	#include <math.h>

#include "types.h"
#include "emu.h"

#include "audio.h"


int mute_audio;


void audio_store(u16 val, u32 addr)
{
	if (addr == 0x340b)
		mem[addr] &= ~val;
	else
		mem[addr] = val;

	if (addr < 0x3200) {		// XXX
		return;
	} else if (addr < 0x3400) {	// XXX
		return;
	} else {			// XXX control regs
		return;
	}

	printf("AUDIO STORE %04x to %04x\n", val, addr);
}

u16 audio_load(u32 addr)
{
	u16 val = mem[addr];

	if (addr >= 0x3000 && addr < 0x3200) {		// audio something
		//printf("LOAD %04x from %04x\n", val, addr);
		return val;
	}
	if (addr >= 0x3200 && addr < 0x3300) {		// audio something
		//printf("LOAD %04x from %04x\n", val, addr);
		return val;
	}
	if (addr >= 0x3400 && addr < 0x3500) {		// audio something
		//printf("LOAD %04x from %04x\n", val, addr);
		return val;
	}

	printf("UNKNOWN AUDIO LOAD from %04x\n", addr);
	return val;
}

static u32 get_channel_bit(u32 ch, u32 reg)
{
	reg += 0x3400;
	if (ch >= 16) {
		reg += 0x0100;
		ch -= 16;
	}
	return (mem[reg] >> ch) & 1;
}

static u32 n_left[24];
static u16 bits_left[24];
static void do_next_sample(u32 ch)
{
loop:
	if (n_left[ch] == 0) {
		u32 addr = ((mem[0x3001 + 16*ch] & 0x3f) << 16) | mem[0x3000 + 16*ch];
		bits_left[ch] = mem[addr];
		if (bits_left[ch] == 0xffff) {
			mem[0x3000 + 16*ch] = mem[0x3002 + 16*ch];
			mem[0x3001 + 16*ch] &= 0xffc0;
			mem[0x3001 + 16*ch] |= (mem[0x3001 + 16*ch] >> 6) & 0x3f;
			goto loop;
		}
		n_left[ch] = 2;
		mem[0x3000 + 16*ch]++;
		if (mem[0x3000 + 16*ch] == 0)
			mem[0x3001 + 16*ch]++;	// XXX: mask?
//printf("--> addr = %06x\n", addr);
	}

	mem[0x300b + 16*ch] = bits_left[ch] << 8;
	bits_left[ch] >>= 8;
	n_left[ch]--;
}

#define FREQ 440
static u16 next_channel_sample(u32 ch)
{
//	if (ch)
//		return 0x8000;

//	static u32 xxx[24] = {0};
//	u16 sample = 0x8000 + (int)(20000*sin(2*M_PI*xxx[ch]*FREQ/281250));
//	xxx[ch]++;
//	if (xxx[ch] == 281250)
//		xxx[ch] = 0;
//	return sample;

	u16 sample = mem[0x300b + 16*ch];
	u32 acc = (mem[0x3201 + 16*ch] << 16) | mem[0x3205 + 16*ch];
	u32 inc = (mem[0x3200 + 16*ch] << 16) | mem[0x3204 + 16*ch];
	acc += inc;
	if (acc >= 0x80000) {
		do_next_sample(ch);
		acc -= 0x80000;
	}
	mem[0x3201 + 16*ch] = acc >> 16;
	mem[0x3205 + 16*ch] = acc;

	return sample;
}

static u16 next_sample(void)
{
	static u32 ch = 0;
	u16 sample;
	if (get_channel_bit(ch, 0))
		sample = next_channel_sample(ch);
	else
		sample = 0x8000;
	ch++;
	if (ch == 24)
		ch = 0;
	return sample;
}

static s16 next_host_sample(void)
{
	if (mem[0x3d20] & 0x0002)	// audio DAC disable
		return 0;

return 0;
	u32 acc = 0;
	u32 i;
	for (i = 0; i < 153; i++)
		acc += next_sample();
	return (acc / 153) - 0x8000;
}

void audio_render(s16 *data, u32 n)
{
	u32 i;
	for (i = 0; i < n; i++)
		data[i] = next_host_sample();
}

void audio_init(void)
{
}