Просмотр исходного кода

Add Volume + Actually Play Tone

[Problem]
Need to actually play the sound, but this also
requires the volume to be adjustable.

[Solution]
Used the audio HAL APIs to play the tone and added
volume to the ToneData structure that is configurable
in the settings.

[Testing]
Confirmed working on device.
Gerald McAlister 2 лет назад
Родитель
Сommit
811047abaf

+ 1 - 1
application.fam

@@ -13,5 +13,5 @@ App(
     fap_author="Gerald McAlister",
     fap_weburl="https://github.com/GEMISIS/tone_gen",
     fap_icon_assets="images",  # Image assets to compile for this application
-    sources=["src/*.c", "src/scenes/*.c", "src/utils/*.c"],
+    sources=["src/*.c", "src/scenes/*.c", "src/system/*.c", "src/utils/*.c"],
 )

+ 11 - 0
src/scenes/playback_scene.c

@@ -1,6 +1,9 @@
+#include <furi_hal.h>
+
 #include "playback_scene.h"
 #include "../app_context.h"
 #include "../tone_gen.h"
+#include "../system/audio_helper.h"
 
 #define SINE_WAVE(x, toneModelData) \
     (sin((x + toneDataModel->animationOffset) * 50) * 20 + (64 / 2))
@@ -56,10 +59,16 @@ void scene_on_enter_playback_scene(void* context) {
     struct ToneData_t* toneDataModel = (struct ToneData_t*)view_get_model(playbackView->viewData);
     toneDataModel->waveType = ((struct ToneData_t*)app->additionalData)->waveType;
     toneDataModel->frequency = ((struct ToneData_t*)app->additionalData)->frequency;
+    toneDataModel->volume = ((struct ToneData_t*)app->additionalData)->volume;
 
     // Set the currently active view
     FURI_LOG_I(TAG, "setting active view");
     view_dispatcher_switch_to_view(app->view_dispatcher, ToneGenAppView_PlaybackView);
+
+    if(initializeSpeaker()) {
+        FURI_LOG_I(TAG, "Starting sound");
+        startSound(toneDataModel);
+    }
 }
 
 // Not actively used in this instance.
@@ -74,4 +83,6 @@ bool scene_on_event_playback_scene(void* context, SceneManagerEvent event) {
 void scene_on_exit_playback_scene(void* context) {
     FURI_LOG_I(TAG, "scene_on_exit_playback_scene");
     UNUSED(context);
+    stopSound();
+    deinitializeSpeaker();
 }

+ 26 - 0
src/scenes/settings_scene.c

@@ -38,6 +38,15 @@ static void frequency_option_change(VariableItem* item) {
     variable_item_set_current_value_text(item, frequencyStr);
 }
 
+char* volumeStr;
+static void volume_option_change(VariableItem* item) {
+    struct AppContext_t* app = variable_item_get_context(item);
+    uint8_t index = variable_item_get_current_value_index(item);
+    ((struct ToneData_t*)app->additionalData)->volume = ((float)(index)) / 10.0f;
+    snprintf(volumeStr, 5, "%d", (index * 10));
+    variable_item_set_current_value_text(item, volumeStr);
+}
+
 /** resets the menu, gives it content, callbacks and selection enums */
 void scene_on_enter_settings_scene(void* context) {
     FURI_LOG_I(TAG, "scene_on_enter_settings_scene");
@@ -51,6 +60,7 @@ void scene_on_enter_settings_scene(void* context) {
     variable_item_list_reset(variableItemListView->viewData);
 
     FURI_LOG_D(TAG, "Adding options for settings");
+    // Wave type setting
     VariableItem* item = variable_item_list_add(
         variableItemListView->viewData,
         "Wave Type",
@@ -62,6 +72,7 @@ void scene_on_enter_settings_scene(void* context) {
     variable_item_set_current_value_text(
         item, wave_option_names[((struct ToneData_t*)app->additionalData)->waveType]);
 
+    // Frequency setting
     item = variable_item_list_add(
         variableItemListView->viewData,
         "Frequency",
@@ -75,6 +86,20 @@ void scene_on_enter_settings_scene(void* context) {
     snprintf(frequencyStr, 8, "%dhz", ((struct ToneData_t*)app->additionalData)->frequency);
     variable_item_set_current_value_text(item, frequencyStr);
 
+    // Volume setting
+    item = variable_item_list_add(
+        variableItemListView->viewData, "Volume", 11, volume_option_change, app);
+    variable_item_set_current_value_index(
+        item, (uint8_t)(((struct ToneData_t*)app->additionalData)->volume * 10.0f));
+
+    volumeStr = calloc(8, sizeof(char));
+    snprintf(
+        volumeStr,
+        5,
+        "%d",
+        ((uint8_t)(((struct ToneData_t*)app->additionalData)->volume * 100.0f)));
+    variable_item_set_current_value_text(item, volumeStr);
+
     view_dispatcher_switch_to_view(app->view_dispatcher, ToneGenAppView_VariableItemList);
 }
 
@@ -90,4 +115,5 @@ void scene_on_exit_settings_scene(void* context) {
     FURI_LOG_I(TAG, "scene_on_exit_settings_scene");
     UNUSED(context);
     free(frequencyStr);
+    free(volumeStr);
 }

+ 28 - 0
src/system/audio_helper.c

@@ -0,0 +1,28 @@
+#include "audio_helper.h"
+
+bool initializeSpeaker() {
+    return furi_hal_speaker_acquire(SPEAKER_TIMEOUT);
+}
+
+bool startSound(struct ToneData_t* toneData) {
+    bool hasSpeaker = furi_hal_speaker_is_mine();
+    if(!hasSpeaker) {
+        hasSpeaker = furi_hal_speaker_acquire(SPEAKER_TIMEOUT);
+    }
+
+    if(hasSpeaker) {
+        FURI_LOG_I(TAG, "Sound is beginning to play");
+        furi_hal_speaker_start(toneData->frequency, toneData->volume);
+    } else {
+        FURI_LOG_E(TAG, "Error acquiring speaker!");
+    }
+    return hasSpeaker;
+}
+
+void stopSound() {
+    furi_hal_speaker_stop();
+}
+
+void deinitializeSpeaker() {
+    furi_hal_speaker_release();
+}

+ 16 - 0
src/system/audio_helper.h

@@ -0,0 +1,16 @@
+#ifndef _AUDIO_HELPER_H_
+
+#define _AUDIO_HELPER_H_
+
+#include <furi_hal.h>
+
+#include "../tone_gen.h"
+
+#define SPEAKER_TIMEOUT 10
+
+bool initializeSpeaker();
+bool startSound(struct ToneData_t* toneData);
+void stopSound();
+void deinitializeSpeaker();
+
+#endif

+ 1 - 0
src/tone_gen.c

@@ -116,6 +116,7 @@ int32_t tone_gen_app(void* p) {
         ((struct ToneData_t*)appContext->additionalData)->animationOffset = 0;
         ((struct ToneData_t*)appContext->additionalData)->frequency = 440;
         ((struct ToneData_t*)appContext->additionalData)->waveType = SINE;
+        ((struct ToneData_t*)appContext->additionalData)->volume = 1.0f;
 
         result = setupViews(&appContext);
         if(result == 0) {

+ 1 - 1
src/tone_gen.h

@@ -5,7 +5,6 @@
 #define TAG "tone-gen"
 
 #include <furi.h>
-#include <music_worker/music_worker.h>
 
 // ids for all scenes used by the app
 typedef enum {
@@ -31,6 +30,7 @@ struct ToneData_t {
     int animationOffset;
     ToneWaveType waveType;
     uint16_t frequency;
+    float volume;
 };
 
 #endif