From cc8dcfacb3c63f9ca928fb54ee6d1558e89e07fc Mon Sep 17 00:00:00 2001 From: Mitchell Marino Date: Wed, 26 Mar 2025 03:47:06 -0500 Subject: [PATCH] WE HAVE A GOOD SPEAKER DRIVER!!!! --- main/drivers/sd.h | 2 +- main/drivers/speaker.cpp | 344 +++++++++++++++--------------------- main/drivers/speaker.h | 33 ++-- main/main.cpp | 2 +- main/steps/step1.cpp | 2 +- main/steps/step2.cpp | 2 +- main/steps/step3.cpp | 18 +- main/steps/step4.cpp | 44 ++--- main/steps/step5.cpp | 2 +- main/steps/step6.cpp | 2 +- main/steps/wires_puzzle.cpp | 2 +- main/steps/wires_puzzle.h | 3 +- 12 files changed, 190 insertions(+), 266 deletions(-) diff --git a/main/drivers/sd.h b/main/drivers/sd.h index 2ff79a6..010d1ae 100644 --- a/main/drivers/sd.h +++ b/main/drivers/sd.h @@ -8,7 +8,7 @@ #include "sdmmc_cmd.h" #include "driver/sdmmc_host.h" -#define MOUNT_POINT "/sdcard" +#define MOUNT_POINT "/sd" extern sdmmc_card_t *card; diff --git a/main/drivers/speaker.cpp b/main/drivers/speaker.cpp index bceae1d..d9effd9 100644 --- a/main/drivers/speaker.cpp +++ b/main/drivers/speaker.cpp @@ -2,6 +2,8 @@ static const char *TAG = "speaker"; +static size_t audio_block_size = 4096; + typedef struct { /// The path to the file being played. char* file_name; @@ -13,59 +15,119 @@ typedef struct { bool repeat; } playing_audio_clip_t; +// It's hard to get the tx_chan's internal state, so instead, we keep track of it here. +bool channel_enabled = false; i2s_chan_handle_t tx_chan; +/// A queue of owned `char*` to be stopped from playing. +/// +/// the speaker driver system will free the given char* when it is done with it. +QueueHandle_t stop_clip_queue; /// A queue of `audio_clip_t`s to be played once there is nothing being played -QueueHandle_t sequential_clip_queue; +QueueHandle_t play_clip_queue; /// The clips that are currently playing std::vector playing_clips; -static void speaker_task(void* arg) { - audio_clip_t next_clip; - playing_audio_clip_t playing_next_clip; - - int16_t* audio_buf = (int16_t*) malloc(AUDIO_BLOCK_SIZE * sizeof(int16_t)); - int16_t* file_buf = (int16_t*) malloc(AUDIO_BLOCK_SIZE * sizeof(int16_t)); - - // wait for a clip request. - while (!xQueueReceive(sequential_clip_queue, &next_clip, portMAX_DELAY)); - ESP_LOGI(TAG, "opening %s", next_clip.file_name); - FILE* fh = fopen(next_clip.file_name, "rb"); - if (fh != NULL) { - ESP_LOGI(TAG, "fh was not null!"); +static bool push_clip(audio_clip_t clip) { + ESP_LOGD(TAG, "playing %s", clip.file_name); + FILE* fh = fopen(clip.file_name, "rb"); + if (fh == NULL) { + ESP_LOGW(TAG, "failed to open %s", clip.file_name); + return false; + } else { // skip the .wav header fseek(fh, 44, SEEK_SET); - playing_next_clip = { - .file_name = next_clip.file_name, + playing_audio_clip_t playing_clip = { + .file_name = clip.file_name, .file_handle = fh, - .prescaler = next_clip.prescaler, - .repeat = next_clip.repeat, + .prescaler = clip.prescaler, + .repeat = clip.repeat, }; - playing_clips.push_back(playing_next_clip); - } else { - ESP_LOGI(TAG, "null :("); + playing_clips.push_back(playing_clip); + return true; } +} + +/// @brief Disables the channel if neccesary. +static void disable_channel() { + if (channel_enabled) { + ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_disable(tx_chan)); + channel_enabled = false; + } +} +/// @brief Enables the channel if neccesary +static void enable_channel() { + if (!channel_enabled) { + ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_enable(tx_chan)); + channel_enabled = true; + } +} + +static void speaker_task(void* arg) { + audio_clip_t next_clip; + char* clip_to_stop; + + int16_t* audio_buf = (int16_t*) malloc(audio_block_size * sizeof(int16_t)); + int16_t* file_buf = (int16_t*) malloc(audio_block_size * sizeof(int16_t)); - i2s_channel_enable(tx_chan); while (1) { - std::memset(audio_buf, 0, AUDIO_BLOCK_SIZE * sizeof(int16_t)); + // first, take all "play immediatly" clips from the queue. + while (xQueuePeek(play_clip_queue, &next_clip, 0) == pdTRUE && next_clip.play_immediatly) { + if (xQueueReceive(play_clip_queue, &next_clip, 0) == pdTRUE) { + push_clip(next_clip); + } + } + + // handle any stop requests + while (xQueueReceive(stop_clip_queue, &clip_to_stop, 0) == pdTRUE) { + // delete clip from list + bool found = false; + for (int clip_idx = playing_clips.size()-1; clip_idx >= 0; clip_idx--) { + playing_audio_clip_t& clip = playing_clips.at(clip_idx); + if (strcmp(clip.file_name, clip_to_stop) == 0) { + found = true; + ESP_LOGV(TAG, "stopping %s", clip.file_name); + fclose(clip.file_handle); + free(clip.file_name); + playing_clips.erase(playing_clips.begin() + clip_idx); + } + } + if (!found) { + ESP_LOGW(TAG, "Could not find clip \"%s\" to stop", clip_to_stop); + } + // free the string that was passed into the queue + free(clip_to_stop); + } + + // if we aren't playing any clips, wait for the next one. + if (playing_clips.empty()) { + if (xQueueReceive(play_clip_queue, &next_clip, 0) == pdTRUE) { + push_clip(next_clip); + } else { + // we must wait before our next clip + disable_channel(); + // now wait for next clip + if (xQueueReceive(play_clip_queue, &next_clip, portMAX_DELAY) == pdTRUE) { + push_clip(next_clip); + } + } + } + + // send 1 block + std::memset(audio_buf, 0, audio_block_size * sizeof(int16_t)); - ESP_LOGI(TAG, "size: %d", playing_clips.size()); for (int clip_idx = playing_clips.size()-1; clip_idx >= 0; clip_idx--) { - ESP_LOGI(TAG, "i: %d", clip_idx); playing_audio_clip_t& clip = playing_clips.at(clip_idx); - ESP_LOGI(TAG, "r %d", (size_t) clip.file_handle); - // ESP_LOGI(TAG, "reading from %s", clip.file_name); - size_t samples_read = fread(file_buf, sizeof(uint16_t), AUDIO_BLOCK_SIZE, clip.file_handle); - ESP_LOGI(TAG, "read! %d", samples_read); + + size_t samples_read = fread(file_buf, sizeof(uint16_t), audio_block_size, clip.file_handle); if (samples_read == 0) { if (clip.repeat) { - ESP_LOGI(TAG, "repeating..."); - fseek(fh, 44, SEEK_SET); + ESP_LOGV(TAG, "repeating %s", clip.file_name); + fseek(clip.file_handle, 44, SEEK_SET); } else { - ESP_LOGI(TAG, "deleting..."); + ESP_LOGV(TAG, "finishing %s", clip.file_name); fclose(clip.file_handle); free(clip.file_name); playing_clips.erase(playing_clips.begin() + clip_idx); @@ -78,166 +140,48 @@ static void speaker_task(void* arg) { } } + size_t bytes_to_write = audio_block_size * sizeof(int16_t); size_t bytes_written; - i2s_channel_write(tx_chan, audio_buf, AUDIO_BLOCK_SIZE * sizeof(int16_t), &bytes_written, portMAX_DELAY); + if (!channel_enabled) { + ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_preload_data(tx_chan, audio_buf, bytes_to_write, &bytes_written)); + enable_channel(); + } else { + ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_write(tx_chan, audio_buf, bytes_to_write, &bytes_written, portMAX_DELAY)); + } + if (bytes_written != bytes_to_write) { + ESP_LOGW(TAG, "only %d bytes written to the i2s channel! (expected %d)", bytes_written, bytes_to_write); + } } - - - // xQueuePeek(sequential_clip_queue, &next_clip, 0); - - // QueueHandle_t stop_music = xQueueCreate(2, sizeof (uint8_t)); - // if (stop_music == 0) { - // ESP_LOGW(TAG, "Could not create stop_music queue!"); - // vTaskDelete(NULL); - // } - - // while (playing_music) { - // play_raw_stop_queue(MOUNT_POINT "/tetris.pcm", stop_music); - // } - vTaskDelete(NULL); } -esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle) { - FILE *fh = fopen(fp, "rb"); - if (fh == NULL) { - ESP_LOGE(TAG, "Failed to open file"); - return ESP_ERR_INVALID_ARG; +bool play_clip_wav(const char* file_name, bool play_immediatly, bool repeat, uint8_t prescaler, TickType_t ticks_to_wait) { + // clone the passed in string to the heap. + size_t len = strlen(file_name); + char* dynamic_file_name = (char*) malloc(len+1); + strcpy(dynamic_file_name, file_name); + + audio_clip_t clip = { + .file_name = dynamic_file_name, + .prescaler = prescaler, + .repeat = repeat, + .play_immediatly = play_immediatly, + }; + + if (play_immediatly) { + return xQueueSendToFront(play_clip_queue, &clip, ticks_to_wait) == pdTRUE; } - - - // create a writer buffer - uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BLOCK_SIZE, sizeof(uint8_t)); - uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BLOCK_SIZE, sizeof(uint16_t)); - size_t bytes_read = 0; - size_t bytes_written = 0; - - esp_err_t channel_enable_result = i2s_channel_enable(tx_chan); - ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result); - if (channel_enable_result != ESP_OK) { - return channel_enable_result; - } - - bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BLOCK_SIZE, fh); - for (int i = 0; i < bytes_read; i++) { - write_buf[i] = read_buf[i] << 4; - } - - // i2s_channel_enable(tx_handle); - - while (bytes_read > 0) { - // write the buffer to the i2s - // ESP_LOGI(TAG, "Writing: "); - // for (int i = 0; i < words_read; i++) { - // int16_t val = buf[i]; - // printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val)); - // }> - i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY); - bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BLOCK_SIZE, fh); - for (int i = 0; i < bytes_read; i++) { - write_buf[i] = read_buf[i] << 4; - } - uint8_t recv = 0; - if (xQueueReceive(stop_handle, &recv, 0)) { - break; - } - vTaskDelay(pdMS_TO_TICKS(10)); - } - - i2s_channel_disable(tx_chan); - free(read_buf); - free(write_buf); - fclose(fh); - - return ESP_OK; + return xQueueSend(play_clip_queue, &clip, ticks_to_wait) == pdTRUE; } -esp_err_t play_wav(const char *fp) { - FILE *fh = fopen(fp, "rb"); - if (fh == NULL) { - ESP_LOGE(TAG, "Failed to open file"); - return ESP_ERR_INVALID_ARG; - } +bool stop_clip(const char* file_name, TickType_t ticks_to_wait) { + // clone the passed in string to the heap. + size_t len = strlen(file_name); + char* dynamic_file_name = (char*) malloc(len+1); + strcpy(dynamic_file_name, file_name); - // skip the header... - fseek(fh, 44, SEEK_SET); - - int16_t *buf = (int16_t*) calloc(AUDIO_BLOCK_SIZE, sizeof(int16_t)); - size_t bytes_read = 0; - size_t bytes_written = 0; - - bytes_read = fread(buf, sizeof(int16_t), AUDIO_BLOCK_SIZE, fh); - for (int i = 0; i < bytes_read; i++) { - buf[i] = buf[i] >> 2; - } - - i2s_channel_preload_data(tx_chan, buf, bytes_read * sizeof(int16_t), &bytes_written); - i2s_channel_enable(tx_chan); - - while (bytes_read > 0) - { - bytes_read = fread(buf, sizeof(int16_t), AUDIO_BLOCK_SIZE, fh); - for (int i = 0; i < bytes_read; i++) { - buf[i] = buf[i] >> 2; - } - // write the buffer to the i2s - i2s_channel_write(tx_chan, buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY); - // ESP_LOGI(TAG, "Bytes read: %d", bytes_read); - } - - i2s_channel_disable(tx_chan); - free(buf); - - return ESP_OK; -} - -esp_err_t play_raw(const char *fp) { - FILE *fh = fopen(fp, "rb"); - if (fh == NULL) { - ESP_LOGE(TAG, "Failed to open file"); - return ESP_ERR_INVALID_ARG; - } - - // create a writer buffer - uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BLOCK_SIZE, sizeof(uint8_t)); - uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BLOCK_SIZE, sizeof(uint16_t)); - size_t bytes_read = 0; - size_t bytes_written = 0; - - bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BLOCK_SIZE, fh); - for (int i = 0; i < bytes_read; i++) { - write_buf[i] = read_buf[i] << 4; - } - - i2s_channel_preload_data(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written); - esp_err_t channel_enable_result = i2s_channel_enable(tx_chan); - ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result); - if (channel_enable_result != ESP_OK) { - return channel_enable_result; - } - - while (bytes_read > 0) { - // write the buffer to the i2s - // ESP_LOGI(TAG, "Writing: "); - // for (int i = 0; i < words_read; i++) { - // int16_t val = buf[i]; - // printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val)); - // }> - bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BLOCK_SIZE, fh); - for (int i = 0; i < bytes_read; i++) { - write_buf[i] = read_buf[i] << 4; - } - vTaskDelay(pdMS_TO_TICKS(10)); - i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY); - } - - i2s_channel_disable(tx_chan); - free(read_buf); - free(write_buf); - fclose(fh); - - return ESP_OK; + return xQueueSend(play_clip_queue, &dynamic_file_name, ticks_to_wait) == pdTRUE; } void init_speaker(void) { @@ -264,32 +208,20 @@ void init_speaker(void) { }; ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg)); - // init queues and list - sequential_clip_queue = xQueueCreate(8, sizeof(audio_clip_t)); + i2s_chan_info_t info = {}; + i2s_channel_get_info(tx_chan, &info); + if (info.total_dma_buf_size != 0) { + audio_block_size = info.total_dma_buf_size / sizeof(int16_t); + } + + // init queues + play_clip_queue = xQueueCreate(CLIP_QUEUE_SIZE, sizeof(audio_clip_t)); + stop_clip_queue = xQueueCreate(CLIP_QUEUE_SIZE, sizeof(char*)); // start task - // TODO: make stack 4096 again :( - xTaskCreate(speaker_task, "play_audio", 16384, NULL, 5, NULL); - - // ESP_ERROR_CHECK_WITHOUT_ABORT(play_wav(MOUNT_POINT "/startup.wav")); - // ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw(MOUNT_POINT "/boot.pcm")); - - char* file_name = (char*) malloc(sizeof(MOUNT_POINT "/startup.wav")); - memcpy(file_name, MOUNT_POINT "/startup.wav", sizeof(MOUNT_POINT "/startup.wav")); - - audio_clip_t startup_clip = { - .file_name = file_name, - .prescaler = 1, - .repeat = false, - .play_immediatly = false, - }; - - xQueueSend(sequential_clip_queue, &startup_clip, 0); - vTaskDelay(pdMS_TO_TICKS(5000)); + xTaskCreate(speaker_task, "play_audio", 4096, NULL, 5, NULL); + play_clip_wav(MOUNT_POINT "/startup.wav", true, false, 3, 0); + ESP_LOGI(TAG, "Speaker initialized!"); } - -void play_example() { - ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw("/sdcard/o.pcm")); -} diff --git a/main/drivers/speaker.h b/main/drivers/speaker.h index c8f99de..f27b45f 100644 --- a/main/drivers/speaker.h +++ b/main/drivers/speaker.h @@ -19,11 +19,8 @@ #define SPEAKER_PIN_WS GPIO_NUM_9 #define SPEAKER_PIN_DOUT GPIO_NUM_3 #define SAMPLE_RATE 44100 -#define PLAY_QUEUE_SIZE 8 -// The maximum number of clips that can be playing at one time. -#define PLAYING_CLIP_SIZE 8 -// Audio will be processed in blocks of this many samples -#define AUDIO_BLOCK_SIZE 2048 +// The maximum number of clips that can be queued at one time. +#define CLIP_QUEUE_SIZE 8 extern i2s_chan_handle_t tx_chan; @@ -41,14 +38,26 @@ typedef struct { bool play_immediatly; } audio_clip_t; -/// Plays a audio file stopping when something is received on `stop_handle` -/// -/// `stop_handle` should be of size `uint8_t`. -esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle); -esp_err_t play_raw(const char *fp); - /// @brief Initalizes the speaker void init_speaker(); -void play_example(); + +/// @brief Plays a wav audio clip. +/// @param file_name The name of the file to play. Fully qualified with the `.wav` extention. +/// @param play_immediatly If `true`, the file will play immediatly even if there is already +/// another clip being played. The two clips will play simultaniously. If `false` the clip +/// will play once all the previous clips have finished. +/// @param repeat If `true` the clip will repeat until stopped. If `false` the clip will +/// stop when finished. +/// @param prescaler A number to shift right all samples by. This makes the music half as +/// loud. Useful for loud audio files. +/// @param ticks_to_wait The number of ticks to wait if the queue is full. +/// @return true if the clip was added to the queue. +bool play_clip_wav(const char* file_name, bool play_immediatly, bool repeat, uint8_t prescaler, TickType_t ticks_to_wait); + +/// @brief Stops an audio clip from playing. +/// @param file_name The file name of the audio clip that was played. +/// @param ticks_to_wait The number of ticks to wait if the queue is full. +/// @return true if the clip was added to the queue. +bool stop_clip(const char* file_name, TickType_t ticks_to_wait); #endif /* SPEAKER_H */ \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp index 450c6da..55779ba 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -49,7 +49,7 @@ extern "C" void app_main(void) { stop_game_timer(); ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win."); - ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw("/sdcard/diffused.pcm")); + play_clip_wav(MOUNT_POINT "/diffused.wav", true, false, 3, 0); display_game_results(); } diff --git a/main/steps/step1.cpp b/main/steps/step1.cpp index 7ca3ac4..05106f8 100644 --- a/main/steps/step1.cpp +++ b/main/steps/step1.cpp @@ -264,7 +264,7 @@ static bool play_part(uint32_t time) { xSemaphoreGive(xGuiSemaphore); } vTaskDelay(pdMS_TO_TICKS(80)); - play_raw(MOUNT_POINT "/correct.pcm"); + play_clip_wav(MOUNT_POINT "/correct.wav", true, false, 3, 0); return true; } diff --git a/main/steps/step2.cpp b/main/steps/step2.cpp index 92de8c1..cf7fa11 100644 --- a/main/steps/step2.cpp +++ b/main/steps/step2.cpp @@ -100,7 +100,7 @@ void step2(void) { char c = char_of_keypad_key(key); // ESP_LOGI(TAG, "Pressed: %c", c); if (c == answer_char) { - play_raw(MOUNT_POINT "/correct.pcm"); + play_clip_wav(MOUNT_POINT "/correct.wav", true, false, 3, 0); solved_times++; if (solved_times < NUM_SOLVES) { clean_bomb(); diff --git a/main/steps/step3.cpp b/main/steps/step3.cpp index 5d4c5b7..438969c 100644 --- a/main/steps/step3.cpp +++ b/main/steps/step3.cpp @@ -13,12 +13,12 @@ static int tone = 0; static int times = 0; static const char* TONE_FILES[] = { - MOUNT_POINT "/low-1.pcm", - MOUNT_POINT "/low-3.pcm", - MOUNT_POINT "/low-6.pcm", - MOUNT_POINT "/high-1.pcm", - MOUNT_POINT "/high-3.pcm", - MOUNT_POINT "/high-6.pcm", + MOUNT_POINT "/low-1.wav", + MOUNT_POINT "/low-3.wav", + MOUNT_POINT "/low-6.wav", + MOUNT_POINT "/high-1.wav", + MOUNT_POINT "/high-3.wav", + MOUNT_POINT "/high-6.wav", }; static const char* LCD_STRINGS[] = { @@ -80,8 +80,8 @@ void step3(void) { // tone = 2; while (get_button_pressed(nullptr)) vTaskDelay(pdMS_TO_TICKS(10)); - play_raw(MOUNT_POINT "/que.pcm"); - play_raw(TONE_FILES[tone]); + play_clip_wav(MOUNT_POINT "/correct.wav", true, false, 3, 0); + play_clip_wav(TONE_FILES[tone], false, false, 3, 0); bool correct = false; switch (tone % 3) { @@ -98,7 +98,7 @@ void step3(void) { if (correct) { times++; clean_bomb(); - play_raw(MOUNT_POINT "/correct.pcm"); + play_clip_wav(MOUNT_POINT "/correct.wav", true, false, 3, 0); } else { vTaskDelay(pdMS_TO_TICKS(1500)); } diff --git a/main/steps/step4.cpp b/main/steps/step4.cpp index f5e5ce1..e96401b 100644 --- a/main/steps/step4.cpp +++ b/main/steps/step4.cpp @@ -18,8 +18,8 @@ static lv_obj_t* line_clear_img; static lv_style_t game_over_style; static lv_obj_t* game_over_label; -static const void* LINE_CLEAR_SRC = (void*)"A:/sdcard/clear.bin"; -static const void* BACKGROUND_SRC = (void*)"A:/sdcard/bg.bin"; +static const void* LINE_CLEAR_SRC = (void*)"A:" MOUNT_POINT "/clear.bin"; +static const void* BACKGROUND_SRC = (void*)"A:" MOUNT_POINT "/bg.bin"; // LV_IMG_DECLARE(background); // static const void* BACKGROUND_SRC = (void*)&background; @@ -28,13 +28,13 @@ static bool playing_music = true; static const char* PIECE_IMG_SRC[] = { NULL, - "A:/sdcard/lb.bin", - "A:/sdcard/db.bin", - "A:/sdcard/orange.bin", - "A:/sdcard/yellow.bin", - "A:/sdcard/green.bin", - "A:/sdcard/purple.bin", - "A:/sdcard/red.bin", + "A:" MOUNT_POINT "/lb.bin", + "A:" MOUNT_POINT "/db.bin", + "A:" MOUNT_POINT "/orange.bin", + "A:" MOUNT_POINT "/yellow.bin", + "A:" MOUNT_POINT "/green.bin", + "A:" MOUNT_POINT "/purple.bin", + "A:" MOUNT_POINT "/red.bin", }; static bool game = true; @@ -123,22 +123,8 @@ static int bdca(int i) { // [0,1,2,3] -> [ 0,+2,+1,-1] const int map[] = {0, 2, 1, -1}; return map[i]; } - -static void music_task(void* arg) { - stop_music = xQueueCreate(2, sizeof (uint8_t)); - if (stop_music == 0) { - ESP_LOGW(TAG, "Could not create stop_music queue!"); - vTaskDelete(NULL); - } - while (playing_music) { - play_raw_stop_queue(MOUNT_POINT "/tetris.pcm", stop_music); - } - - vTaskDelete(NULL); -} - -static void init_screen(void) { +static void init_screen() { while (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdFALSE) vTaskDelay(pdMS_TO_TICKS(10)); img = lv_img_create(lv_scr_act()); @@ -176,19 +162,17 @@ static void init_screen(void) { xSemaphoreGive(xGuiSemaphore); - xTaskCreate(music_task, "music", 4096, NULL, 5, NULL); + play_clip_wav(MOUNT_POINT "/tetris.wav", true, false, 3, 0); } -static void deinit_screen(void) { +static void deinit_screen() { while (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY) == pdFALSE) vTaskDelay(pdMS_TO_TICKS(10)); lv_obj_clean(lv_scr_act()); xSemaphoreGive(xGuiSemaphore); - playing_music = false; - uint8_t value = 0; - if (!xQueueSend(stop_music, &value, pdMS_TO_TICKS(1000))) { - ESP_LOGE(TAG, "Faild to send stop queue"); + if (!stop_clip(MOUNT_POINT "/tetris.wav", pdMS_TO_TICKS(1000))) { + ESP_LOGW(TAG, "Can't stop, addicted to the shindig."); } } diff --git a/main/steps/step5.cpp b/main/steps/step5.cpp index 3ceae04..165d46e 100644 --- a/main/steps/step5.cpp +++ b/main/steps/step5.cpp @@ -878,7 +878,7 @@ void step5(void) { stop_module_timer(); if (solved_correctly) { solved_puzzles++; - play_raw(MOUNT_POINT "/correct.pcm"); + play_clip_wav(MOUNT_POINT "/correct.wav", true, false, 3, 0); vTaskDelay(pdMS_TO_TICKS(500)); solved_correctly = false; } else { diff --git a/main/steps/step6.cpp b/main/steps/step6.cpp index fb5f62a..fb4508d 100644 --- a/main/steps/step6.cpp +++ b/main/steps/step6.cpp @@ -22,7 +22,7 @@ void step6(void) { for (int i = 0; i < NUM_WIRES; i++) { if (just_cut_wires & (1< #include -#include -#include "esp_vfs_fat.h" +#include "drivers/sd.h" #define NUM_COLORS 6 #define NUM_WIRES 8