this repo has no description
1/*
2 SNDEMDEV.c
3
4 Copyright (C) 2003 Philip Cummins, Paul C. Pratt
5
6 You can redistribute this file and/or modify it under the terms
7 of version 2 of the GNU General Public License as published by
8 the Free Software Foundation. You should have received a copy
9 of the license along with this file; see the file COPYING.
10
11 This file is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 license for more details.
15*/
16
17/*
18 SouND EMulated DEVice
19
20 Emulation of Sound in the Mac Plus could go here.
21
22 This code adapted from "Sound.c" in vMac by Philip Cummins.
23*/
24
25#include "PICOMMON.h"
26
27#if EmClassicSnd
28
29#include "MINEM68K.h"
30
31#include "SNDEMDEV.h"
32
33
34#define kSnd_Main_Offset 0x0300
35#define kSnd_Alt_Offset 0x5F00
36
37#define kSnd_Main_Buffer (kRAM_Size - kSnd_Main_Offset)
38#define kSnd_Alt_Buffer (kRAM_Size - kSnd_Alt_Offset)
39
40/*
41 approximate volume levels of vMac, so:
42
43 x * vol_mult[SoundVolume] >> 16
44 + vol_offset[SoundVolume]
45 = {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound;
46*/
47
48LOCALVAR const ui4b vol_mult[] = {
49 8192, 9362, 10922, 13107, 16384, 21845, 32768
50};
51
52LOCALVAR const trSoundSamp vol_offset[] = {
53#if 3 == kLn2SoundSampSz
54 112, 110, 107, 103, 96, 86, 64, 0
55#elif 4 == kLn2SoundSampSz
56 28672, 28087, 27307, 26215, 24576, 21846, 16384, 0
57#else
58#error "unsupported kLn2SoundSampSz"
59#endif
60};
61
62LOCALVAR const ui4b SubTick_offset[kNumSubTicks] = {
63 0, 25, 50, 90, 102, 115, 138, 161,
64 185, 208, 231, 254, 277, 300, 323, 346
65};
66
67LOCALVAR const ui3r SubTick_n[kNumSubTicks] = {
68 25, 25, 40, 12, 13, 23, 23, 24,
69 23, 23, 23, 23, 23, 23, 23, 24
70};
71
72/*
73 One version of free form sound driver
74 spends around 18000 cycles writing
75 offsets 50 to 370, then around another 3000
76 cycles writing 0 to 50. So be done
77 with 0 to 50 at end of second sixtieth.
78*/
79
80/*
81 Different in system 6.0.4:
82 spends around 23500 cycles writing
83 offsets 90 to 370, then around another 7500
84 cycles writing 0 to 90. This is nastier,
85 because gets to be a very small gap
86 between where is being read and
87 where written. So read a bit in
88 advance for third subtick.
89*/
90
91/*
92 startup sound spends around 19500 cycles
93 writing offsets 0 to 370. presumably
94 writing offset 0 before it is read.
95*/
96
97LOCALVAR ui5b SoundInvertPhase = 0;
98LOCALVAR ui4b SoundInvertState = 0;
99
100IMPORTFUNC ui4b GetSoundInvertTime(void);
101
102GLOBALPROC MacSound_SubTick(int SubTick)
103{
104 ui4r actL;
105 tpSoundSamp p;
106 ui4r i;
107 ui5b StartOffset = SubTick_offset[SubTick];
108 ui4r n = SubTick_n[SubTick];
109 unsigned long addy =
110#ifdef SoundBuffer
111 (SoundBuffer == 0) ? kSnd_Alt_Buffer :
112#endif
113 kSnd_Main_Buffer;
114#ifndef ln2mtb
115 ui3p addr = addy + (2 * StartOffset) + RAM;
116#else
117 CPTR addr = addy + (2 * StartOffset);
118#endif
119 ui4b SoundInvertTime = GetSoundInvertTime();
120 ui3b SoundVolume = SoundVolb0
121 | (SoundVolb1 << 1)
122 | (SoundVolb2 << 2);
123
124#if dbglog_HAVE && 0
125 dbglog_StartLine();
126 dbglog_writeCStr("reading sound buffer ");
127 dbglog_writeHex(StartOffset);
128 dbglog_writeCStr(" to ");
129 dbglog_writeHex(StartOffset + n);
130 dbglog_writeReturn();
131#endif
132
133label_retry:
134 p = MySound_BeginWrite(n, &actL);
135 if (actL > 0) {
136 if (SoundDisable && (SoundInvertTime == 0)) {
137 for (i = 0; i < actL; i++) {
138#if 0
139 *p++ = 0x00; /* this is believed more accurate */
140#else
141 /* But this avoids more clicks. */
142 *p++ = kCenterSound;
143#endif
144 }
145 } else {
146 for (i = 0; i < actL; i++) {
147 /* Copy sound data, high byte of each word */
148 *p++ =
149#ifndef ln2mtb
150 *addr
151#else
152 get_vm_byte(addr)
153#endif
154#if 4 == kLn2SoundSampSz
155 << 8
156#endif
157 ;
158
159 /* Move the address on */
160 addr += 2;
161 }
162
163 if (SoundInvertTime != 0) {
164 ui5b PhaseIncr = (ui5b)SoundInvertTime * (ui5b)20;
165 p -= actL;
166
167 for (i = 0; i < actL; i++) {
168 if (SoundInvertPhase < 704) {
169 ui5b OnPortion = 0;
170 ui5b LastPhase = 0;
171 do {
172 if (! SoundInvertState) {
173 OnPortion +=
174 (SoundInvertPhase - LastPhase);
175 }
176 SoundInvertState = ! SoundInvertState;
177 LastPhase = SoundInvertPhase;
178 SoundInvertPhase += PhaseIncr;
179 } while (SoundInvertPhase < 704);
180 if (! SoundInvertState) {
181 OnPortion += 704 - LastPhase;
182 }
183 *p = (*p * OnPortion) / 704;
184 } else {
185 if (SoundInvertState) {
186 *p = 0;
187 }
188 }
189 SoundInvertPhase -= 704;
190 p++;
191 }
192 }
193 }
194
195 if (SoundVolume < 7) {
196 /*
197 Usually have volume at 7, so this
198 is just for completeness.
199 */
200 ui5b mult = (ui5b)vol_mult[SoundVolume];
201 trSoundSamp offset = vol_offset[SoundVolume];
202
203 p -= actL;
204 for (i = 0; i < actL; i++) {
205 *p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset;
206 ++p;
207 }
208 }
209
210 MySound_EndWrite(actL);
211 n -= actL;
212 if (n > 0) {
213 goto label_retry;
214 }
215 }
216}
217
218#endif /* EmClassicSnd */