| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- #include "audio_prompt.h"
- #include "audio_prompts_data.h"
- #include "audio_output.h"
- #include "esp_log.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "dac_njw1195.h"
- static const char *TAG = "AudioPrompt";
- void audio_prompt_init(void) {
- ESP_LOGI(TAG, "Audio prompt module initialized");
- }
- void audio_prompt_play(prompt_id_t id) {
- const int16_t *prompt_data = NULL;
- size_t prompt_len = 0;
- switch (id) {
- case PROMPT_BT_CONNECTED:
- prompt_data = prompt_bt_connected;
- prompt_len = prompt_bt_connected_len;
- break;
- case PROMPT_BT_DISCONNECTED:
- prompt_data = prompt_bt_disconnected;
- prompt_len = prompt_bt_disconnected_len;
- break;
- case PROMPT_LOW_BATTERY:
- prompt_data = prompt_low_battery;
- prompt_len = prompt_low_battery_len;
- break;
- default:
- return;
- }
- if (prompt_data == NULL || prompt_len == 0) {
- return;
- }
- ESP_LOGI(TAG, "Playing prompt tone ID: %d", id);
- // Lock audio output so we don't interleave with BT/AirPlay
- audio_output_lock();
- // Switch DAC to prompt volume
- dac_njw1195_set_prompt_mode(true);
- // Prompts are generated at 44100Hz 16-bit Mono.
- // audio_output_write expects 16-bit Stereo. We duplicate channels.
- // We send in chunks to avoid large memory allocations.
- const size_t CHUNK_SAMPLES = 256;
- int16_t stereo_buf[CHUNK_SAMPLES * 2];
- for (size_t i = 0; i < prompt_len; i += CHUNK_SAMPLES) {
- size_t samples_to_process = prompt_len - i;
- if (samples_to_process > CHUNK_SAMPLES) {
- samples_to_process = CHUNK_SAMPLES;
- }
- for (size_t j = 0; j < samples_to_process; j++) {
- int16_t sample = prompt_data[i + j];
- stereo_buf[j * 2] = sample; // Left
- stereo_buf[j * 2 + 1] = sample; // Right
- }
- // Write stereo PCM data. audio_output_write internally calls i2s_channel_write.
- audio_output_write(stereo_buf, samples_to_process * 4, portMAX_DELAY);
- }
- // Write silence to flush the DMA buffers.
- // I2S_DMA_DESC_NUM(8) * I2S_DMA_FRAME_NUM(352) = 2816 frames.
- // Writing roughly 3000 frames of silence ensures the prompt is pushed out.
- memset(stereo_buf, 0, sizeof(stereo_buf));
- for (int i = 0; i < 12; i++) { // 12 * 256 = 3072 frames
- audio_output_write(stereo_buf, CHUNK_SAMPLES * 4, portMAX_DELAY);
- }
- // Restore original volume
- dac_njw1195_set_prompt_mode(false);
- audio_output_unlock();
- }
|