/ MCUME_esp32 / espboot / 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  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