/ MCUME_esp32 / espnes / main / AudioPlaySystem.cpp
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