AudioPlaySystem.cpp
1 extern "C" { 2 #include "emuapi.h" 3 } 4 5 #ifdef HAS_SND 6 #include "AudioPlaySystem.h" 7 #include "esp_system.h" 8 9 //#define USE_I2S 1 10 11 #ifdef USE_I2S 12 #include "esp_event.h" 13 #include "driver/i2s.h" 14 #include "freertos/queue.h" 15 #include "string.h" 16 static const i2s_port_t i2s_num = (i2s_port_t)0; 17 static QueueHandle_t queue; 18 19 #else 20 21 #include "esp32-hal-timer.h" 22 #include "esp32-hal-dac.h" 23 static int32_t LastPlayPos=0; 24 volatile int32_t NextPlayPos=0; 25 volatile uint8_t DacPin; 26 uint16_t LastDacValue; 27 hw_timer_t * timer = NULL; 28 29 #endif 30 31 volatile uint16_t *Buffer; 32 volatile uint16_t BufferSize; 33 34 35 static const short square[]={ 36 32767,32767,32767,32767, 37 32767,32767,32767,32767, 38 32767,32767,32767,32767, 39 32767,32767,32767,32767, 40 32767,32767,32767,32767, 41 32767,32767,32767,32767, 42 32767,32767,32767,32767, 43 32767,32767,32767,32767, 44 -32767,-32767,-32767,-32767, 45 -32767,-32767,-32767,-32767, 46 -32767,-32767,-32767,-32767, 47 -32767,-32767,-32767,-32767, 48 -32767,-32767,-32767,-32767, 49 -32767,-32767,-32767,-32767, 50 -32767,-32767,-32767,-32767, 51 -32767,-32767,-32767,-32767, 52 }; 53 54 const short noise[] { 55 -32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767, 56 -32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,32767,-32767, 57 -32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767, 58 -32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767, 59 -32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767, 60 -32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767, 61 32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767, 62 32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767, 63 32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767, 64 32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,-32767,-32767, 65 32767,-32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767, 66 32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,-32767, 67 32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767, 68 32767,-32767,32767,-32767,-32767,32767,32767,-32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767, 69 32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767, 70 32767,-32767,32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767, 71 }; 72 73 #define NOISEBSIZE 0x100 74 75 typedef struct 76 { 77 unsigned int spos; 78 unsigned int sinc; 79 unsigned int vol; 80 } Channel; 81 82 volatile bool playing = false; 83 84 85 static Channel chan[6] = { 86 {0,0,0}, 87 {0,0,0}, 88 {0,0,0}, 89 {0,0,0}, 90 {0,0,0}, 91 {0,0,0} }; 92 93 94 static void snd_Reset(void) 95 { 96 chan[0].vol = 0; 97 chan[1].vol = 0; 98 chan[2].vol = 0; 99 chan[3].vol = 0; 100 chan[4].vol = 0; 101 chan[5].vol = 0; 102 chan[0].sinc = 0; 103 chan[1].sinc = 0; 104 chan[2].sinc = 0; 105 chan[3].sinc = 0; 106 chan[4].sinc = 0; 107 chan[5].sinc = 0; 108 } 109 110 #ifdef CUSTOM_SND 111 //extern "C" { 112 void SND_Process(void *sndbuffer, int sndn); 113 //} 114 #endif 115 116 117 static void snd_Mixer16(uint16_t * stream, int len ) 118 { 119 if (playing) 120 { 121 #ifdef CUSTOM_SND 122 SND_Process((void*)stream, len); 123 #else 124 int i; 125 long s; 126 //len = len >> 1; 127 128 short v0=chan[0].vol; 129 short v1=chan[1].vol; 130 short v2=chan[2].vol; 131 short v3=chan[3].vol; 132 short v4=chan[4].vol; 133 short v5=chan[5].vol; 134 for (i=0;i<len;i++) 135 { 136 s = ( v0*(square[(chan[0].spos>>8)&0x3f]) ); 137 s+= ( v1*(square[(chan[1].spos>>8)&0x3f]) ); 138 s+= ( v2*(square[(chan[2].spos>>8)&0x3f]) ); 139 s+= ( v3*(noise[(chan[3].spos>>8)&(NOISEBSIZE-1)]) ); 140 s+= ( v4*(noise[(chan[4].spos>>8)&(NOISEBSIZE-1)]) ); 141 s+= ( v5*(noise[(chan[5].spos>>8)&(NOISEBSIZE-1)]) ); 142 *stream++ = int16_t((s>>11)); 143 chan[0].spos += chan[0].sinc; 144 chan[1].spos += chan[1].sinc; 145 chan[2].spos += chan[2].sinc; 146 chan[3].spos += chan[3].sinc; 147 chan[4].spos += chan[4].sinc; 148 chan[5].spos += chan[5].sinc; 149 } 150 #endif 151 } 152 } 153 154 #ifdef USE_I2S 155 #else 156 void IRAM_ATTR onTimer() 157 { 158 // Sound playing code, plays whatever's in the buffer continuously. Big change from previous versions 159 if(LastDacValue!=Buffer[NextPlayPos]) // Send value to DAC only of changed since last value else no need 160 { 161 // value to DAC has changed, send to actual hardware, else we just leave setting as is as it's not changed 162 LastDacValue=Buffer[NextPlayPos]; 163 dacWrite(DacPin,uint8_t((LastDacValue>>8)+127)); // write out the data 164 } 165 Buffer[NextPlayPos]=0; // Reset this buffer byte back to silence 166 NextPlayPos++; // Move play pos to next byte in buffer 167 if(NextPlayPos==BufferSize) // If gone past end of buffer, 168 NextPlayPos=0; // set back to beginning 169 } 170 171 #endif 172 173 void AudioPlaySystem::begin(void) 174 { 175 #ifdef USE_I2S 176 Buffer = (uint16_t *)malloc(DEFAULT_SAMPLESIZE*4); //16bits, L+R 177 uint16_t * dst=(uint16_t *)Buffer; 178 for (int i=0; i<DEFAULT_SAMPLESIZE; i++) { 179 *dst++=32767; 180 *dst++=32767; 181 }; 182 183 i2s_config_t cfg={ 184 .mode=(i2s_mode_t)(I2S_MODE_DAC_BUILT_IN|I2S_MODE_TX|I2S_MODE_MASTER), 185 .sample_rate=DEFAULT_SAMPLERATE, 186 .bits_per_sample=I2S_BITS_PER_SAMPLE_16BIT, 187 .channel_format=I2S_CHANNEL_FMT_RIGHT_LEFT, 188 .communication_format=I2S_COMM_FORMAT_I2S_MSB, 189 .intr_alloc_flags=0, 190 .dma_buf_count=4, 191 .dma_buf_len=DEFAULT_SAMPLESIZE*4 192 }; 193 i2s_driver_install(i2s_num, &cfg, 4, &queue); 194 //i2s_driver_install(i2s_num, &cfg, 0, NULL); 195 i2s_set_pin(i2s_num, NULL); 196 i2s_set_dac_mode(I2S_DAC_CHANNEL_LEFT_EN); 197 //I2S enables *both* DAC channels; we only need DAC1. 198 //ToDo: still needed now I2S supports set_dac_mode? 199 CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC_XPD_FORCE_M); 200 CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC_M); 201 #else 202 BufferSize = DEFAULT_SAMPLESIZE; 203 Buffer=(volatile uint16_t *)malloc(BufferSize*2); 204 volatile uint16_t * dst=Buffer; 205 for (int i=0; i<BufferSize; i++) { 206 *dst++=0; 207 }; 208 209 DacPin=25; // set dac pin to use 210 LastDacValue=0; // set to mid point 211 dacWrite(DacPin,LastDacValue); // Set speaker to mid point, stops click at start of first sound 212 // Set up interrupt routine 213 timer = timerBegin(0, 80, true); // use timer 0, pre-scaler is 80 (divide by 8000), count up 214 timerAttachInterrupt(timer, &onTimer, true); // P3= edge triggered 215 timerAlarmWrite(timer, 45, true); // will trigger 22050 times per sec (443 per 20 ms=22050/50) 216 timerAlarmEnable(timer); 217 #endif 218 } 219 220 void AudioPlaySystem::start(void) 221 { 222 playing = true; 223 } 224 225 void AudioPlaySystem::setSampleParameters(float clockfreq, float samplerate) { 226 } 227 228 void AudioPlaySystem::reset(void) 229 { 230 snd_Reset(); 231 } 232 233 void AudioPlaySystem::stop(void) 234 { 235 playing = false; 236 #ifdef USE_I2S 237 i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver 238 #else 239 #endif 240 } 241 242 bool AudioPlaySystem::isPlaying(void) 243 { 244 return playing; 245 } 246 247 248 void AudioPlaySystem::sound(int C, int F, int V) { 249 if (C < 6) { 250 //printf("play %d %d %d\n",C,F,V); 251 252 chan[C].vol = V; 253 chan[C].sinc = F>>1; 254 } 255 } 256 257 void AudioPlaySystem::step(void) 258 { 259 #ifdef USE_I2S 260 int left=DEFAULT_SAMPLERATE/50; 261 262 while(left) { 263 int n=DEFAULT_SAMPLESIZE; 264 if (n>left) n=left; 265 snd_Mixer16((uint16_t*)Buffer, n); 266 //16 bit mono -> 16 bit r+l 267 for (int i=n-1; i>=0; i--) { 268 Buffer[i*2+1]=Buffer[i]; 269 Buffer[i*2]=Buffer[i]; 270 } 271 printf("%d\n",n); 272 i2s_write_bytes(i2s_num, (const void*)Buffer, n*4, portMAX_DELAY); 273 left-=n; 274 } 275 //i2s_write(i2s_num, i2s_write_buff, i2s_wr_len, &bytes_written, portMAX_DELAY); 276 #else 277 278 int32_t CurPos=NextPlayPos; 279 int32_t samples; 280 if (CurPos > LastPlayPos) { 281 snd_Mixer16((uint16_t *)&Buffer[LastPlayPos], CurPos-LastPlayPos); 282 samples = CurPos-LastPlayPos; 283 } 284 else { 285 snd_Mixer16((uint16_t *)&Buffer[LastPlayPos], BufferSize-LastPlayPos); 286 snd_Mixer16((uint16_t *)&Buffer[0], CurPos); 287 samples = BufferSize-LastPlayPos; 288 samples += CurPos; 289 } 290 LastPlayPos = CurPos; 291 //printf("sam %d\n",bytes); 292 #endif 293 } 294 #endif 295 296