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