Browse Source

added dynamic playback

Iver 4 days ago
parent
commit
ba66ca3226

BIN
audio/voice.mp3


BIN
builds/libyuzuparse.so


BIN
builds/main.bin


+ 2 - 1
changelog.txt

@@ -1 +1,2 @@
--blocked PortAudio's terminal output on init
+-made callback exit safer
+-added dynamically playback, can now change speed (can be positive and negative) and can loop audio

+ 1 - 0
src/headers/YZ_functions.h

@@ -5,6 +5,7 @@
 
 
 YZ_audio_stream* YZ_load_audio_file(char* filename, unsigned char debug_mode);
 YZ_audio_stream* YZ_load_audio_file(char* filename, unsigned char debug_mode);
 pa_callback_data* YZ_play_stream(YZ_audio_stream* audio_stream);
 pa_callback_data* YZ_play_stream(YZ_audio_stream* audio_stream);
+pa_callback_data* YZ_play_stream_dynamic(YZ_audio_stream* audio_stream, double* speed_multiplier, unsigned char* should_loop_audio);
 void YZ_init_player();
 void YZ_init_player();
 void YZ_kill_player();
 void YZ_kill_player();
 
 

+ 4 - 1
src/headers/YZ_types.h

@@ -11,10 +11,13 @@ typedef struct {
 } YZ_audio_stream;
 } YZ_audio_stream;
 
 
 typedef struct {
 typedef struct {
-    uint32_t current_sample;
+    float current_sample;
     float* pcm_data;
     float* pcm_data;
     uint32_t channel_count;
     uint32_t channel_count;
     uint32_t sample_count;
     uint32_t sample_count;
+    double* pitch_multiplier;
+    double* speed_multiplier;
+    unsigned char* should_loop_audio;
 } pa_callback_data;
 } pa_callback_data;
 
 
 #endif
 #endif

+ 1 - 0
src/headers/yuzuparse.h

@@ -10,5 +10,6 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <portaudio.h>
 #include <portaudio.h>
 #include <fcntl.h>
 #include <fcntl.h>
+#include <math.h>
 
 
 #endif
 #endif

+ 4 - 1
src/launch program/main.c

@@ -5,8 +5,11 @@ int main(){
 
 
     pa_callback_data* callback_data;
     pa_callback_data* callback_data;
 
 
+    double speed = -1;
+    unsigned char should_loop_audio = 1;
+
     if (audio_stream)
     if (audio_stream)
-        callback_data = YZ_play_stream(audio_stream);
+        callback_data = YZ_play_stream_dynamic(audio_stream, &speed, &should_loop_audio);
     
     
     // wait until audio is finished playing until exiting
     // wait until audio is finished playing until exiting
     while (callback_data->current_sample < callback_data->sample_count){}
     while (callback_data->current_sample < callback_data->sample_count){}

+ 38 - 7
src/main/main.c

@@ -252,18 +252,33 @@ int portaudio_callback(const void* input, void* output, unsigned long frame_coun
 
 
     for(uint32_t i = 0; i < frame_count; i++){
     for(uint32_t i = 0; i < frame_count; i++){
         for (uint32_t j = 0; j < data->channel_count; j++) {
         for (uint32_t j = 0; j < data->channel_count; j++) {
-            *out++ = data->pcm_data[(data->current_sample) * data->channel_count + j];
+            *out++ = data->pcm_data[(int)(data->current_sample) * data->channel_count + j];
         }
         }
 
 
-        data->current_sample++;
-    }
+        data->current_sample += *data->speed_multiplier;
     
     
-    if (data->current_sample < data->sample_count) return 0;
-    else{
+        if (*data->should_loop_audio){
+            if (data->current_sample >= data->sample_count){
+                data->current_sample = data->sample_count - data->current_sample;
+            } else if (data->current_sample < 0){
+                data->current_sample = data->sample_count + data->current_sample;
+            }
+        }
+
+        if (data->current_sample >= data->sample_count || data->current_sample < 0){
+            free(audio_data);
+
+            return 1;
+        }
+    }
+
+    if (data->current_sample >= data->sample_count){
         free(audio_data);
         free(audio_data);
 
 
         return 1;
         return 1;
     }
     }
+    
+    return 0;
 }
 }
 
 
 unsigned char player_is_initialized = 0;
 unsigned char player_is_initialized = 0;
@@ -305,7 +320,7 @@ void YZ_kill_player(){
     if(error != paNoError) { printf("PortAudio error: %d\n", error); exit(1);}
     if(error != paNoError) { printf("PortAudio error: %d\n", error); exit(1);}
 }
 }
 
 
-pa_callback_data* YZ_play_stream(YZ_audio_stream* audio_stream){
+pa_callback_data* play_stream(YZ_audio_stream* audio_stream, double* pitch_multiplier, double* speed_multiplier, unsigned char* should_loop_audio){
     PaError error;
     PaError error;
     
     
     PaStream *stream;
     PaStream *stream;
@@ -316,6 +331,9 @@ pa_callback_data* YZ_play_stream(YZ_audio_stream* audio_stream){
     callback_data->current_sample = 0;
     callback_data->current_sample = 0;
     callback_data->pcm_data = audio_stream->pcm_data;
     callback_data->pcm_data = audio_stream->pcm_data;
     callback_data->sample_count = audio_stream->sample_count;
     callback_data->sample_count = audio_stream->sample_count;
+    callback_data->pitch_multiplier = pitch_multiplier;
+    callback_data->speed_multiplier = speed_multiplier;
+    callback_data->should_loop_audio = should_loop_audio;
 
 
     if (!player_is_initialized) YZ_init_player();
     if (!player_is_initialized) YZ_init_player();
 
 
@@ -325,4 +343,17 @@ pa_callback_data* YZ_play_stream(YZ_audio_stream* audio_stream){
     Pa_StartStream(stream);
     Pa_StartStream(stream);
 
 
     return callback_data;
     return callback_data;
-}
+}
+
+// play an audio stream
+pa_callback_data* YZ_play_stream(YZ_audio_stream* audio_stream){
+    double value = 1;
+    unsigned char antivalue = 0;
+
+    return play_stream(audio_stream, &value, &value, &antivalue);
+}
+
+// play an audio stream and modify pitch and speed dynamically. Pitch and speed changes work in real time due to it being pointers to the values
+pa_callback_data* YZ_play_stream_dynamic(YZ_audio_stream* audio_stream, double* speed_multiplier, unsigned char* should_loop_audio){
+    return play_stream(audio_stream, NULL, speed_multiplier, should_loop_audio);
+}