this repo has no description
at main 218 lines 4.9 kB view raw
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 */