summaryrefslogtreecommitdiffstats
path: root/WasmAudio/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'WasmAudio/main.c')
-rw-r--r--WasmAudio/main.c389
1 files changed, 385 insertions, 4 deletions
diff --git a/WasmAudio/main.c b/WasmAudio/main.c
index b031629..6f1766b 100644
--- a/WasmAudio/main.c
+++ b/WasmAudio/main.c
@@ -5,16 +5,15 @@
// Created by Jacky Jack on 06/07/2021.
//
-#include <stdio.h>
-#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
-#include <strings.h>
+#include <string.h>
#include <getopt.h>
#include <signal.h>
#include <fcntl.h>
#include <pthread.h>
+#include <unistd.h>
@@ -22,9 +21,11 @@
#include <emscripten/emscripten.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
+#include <SDL/SDL_audio.h>
#include <GLES2/gl2.h>
#else
#include <SDL2/SDL.h>
+ #include <SDL2/SDL_audio.h>
#ifdef __APPLE__
#include <SDL2_ttf/SDL_ttf.h>
#else
@@ -34,12 +35,392 @@
//#include <GLES2/gl2.h>
#endif
+#define SCREEN_WIDTH 320
+#define SCREEN_WIDTH2 (SCREEN_WIDTH/2)
+#define SCREEN_HEIGHT 320
+#define SCREEN_HEIGHT2 (SCREEN_HEIGHT/2)
+
+#define BUFSIZE 1536000
+
+//Maximum recording time plus padding
+#define RECORDING_BUFFER_SECONDS (2)
+//Maximum recording time
+#define MAX_RECORDING_SECONDS (RECORDING_BUFFER_SECONDS+2)
+
+int first_run=1;
+static int quit=0;
+static SDL_Window *window = NULL;
+static SDL_Renderer *renderer = NULL;
+//Audio device IDs
+static SDL_AudioDeviceID recordingDeviceId = 0;
+static SDL_AudioDeviceID playbackDeviceId = 0;
+int audio_rec_buffer_size=-1;
+int audio_rec_buffer_max_size=-1;
+//int audio_play_buffer_size=-1;
+//int audio_play_buffer_max_size=-1;
+static uint8_t audio_rec_buffer_[BUFSIZE];
+static double process_buf[BUFSIZE/4];
+uint8_t *audio_rec_buffer=NULL;
+int audio_buf_position=0;
+//uint8_t *audio_play_buffer=NULL;
+int current_state=0;
+
+
+void audio_recording_callback(void *data, uint8_t *insamples, int len)
+{
+ //printf("record len=%d\n",len);
+ if (audio_buf_position<audio_rec_buffer_size) {
+ memcpy( audio_rec_buffer+audio_buf_position, insamples, len);
+ audio_buf_position += len;
+ }
+ //memcpy(insamples, audio_rec_buffer+audio_buf_position, len);
+
+ printf("rec_pos=%d\n",audio_buf_position);
+}
+
+void audio_playback_callback(void *data, uint8_t *outsamples, int len) {
+ //printf("playback len=%d\n",len);
+ //memcpy( audio_rec_buffer,outsamples, len);
+ if (audio_buf_position<audio_rec_buffer_size) {
+ memcpy( outsamples, audio_rec_buffer+audio_buf_position,len);
+ audio_buf_position += len;
+ }
+
+}
+//The various recording actions we can take
+enum RecordingState
+{
+ SELECTING_DEVICE,
+ STOPPED,
+ RECORDING,
+ RECORDED,
+ PLAYBACK,
+ ERROR
+};
+void convert_double_to_f32() {
+ int i;
+ for (i=0;i<audio_rec_buffer_size;i+=4) {
+ float *f_ = (float *)&audio_rec_buffer[i];
+ float f = *f_;
+ process_buf[i/4] = (double)f;
+ }
+}
+
+void convert_f32_to_double() {
+ int i=0;
+ for (i=0;i<audio_rec_buffer_size;i+=4) {
+ double d = process_buf[i/4];
+ float f = (float)d;
+ float *f_ = (float *)audio_rec_buffer;
+ f_[i/4] = (double)f;
+ }
+}
+
+
+uint32_t tick_start, tick_end,tick_1sec;
+
+#if __EMSCRIPTEN__
+void main_tick() {
+#else
+int main_tick() {
+#endif
+ int i,j;
+ int update_fractal=0;
+ uint64_t perf_start, perf_end;
+
+ perf_start = SDL_GetPerformanceCounter();
+ tick_start = SDL_GetTicks();
+
+ SDL_Event event;
+ SDL_StartTextInput();
+ while (SDL_PollEvent(&event) != 0)
+ {
+
+ switch (event.type)
+ {
+ case SDL_QUIT:
+ {
+ quit = 1;
+ break;
+ }
+ case SDL_KEYDOWN:
+ {
+ switch (event.key.keysym.sym)
+ {
+
+ case 21:
+ case SDLK_r:
+ //record if stopped
+ if ((current_state == STOPPED) || (current_state == RECORDED)) {
+ audio_buf_position = 0;
+ SDL_PauseAudioDevice(recordingDeviceId, SDL_FALSE);
+ current_state = RECORDING;
+ printf("State: RECORDING\n");
+ }
+ break;
+ case 22:
+ case SDLK_s:
+ //play if recorded
+ if (current_state == RECORDED) {
+ audio_buf_position = 0;
+ SDL_PauseAudioDevice( playbackDeviceId, SDL_FALSE );
+ current_state = PLAYBACK;
+ printf("State: PLAYBACK\n");
+ } /*else if (current_state == PLAYBACK) {
+ current_state = STOPPED;
+ } else if (current_state == STOPPED) {
+ current_state = PLAYBACK;
+ }*/
+ break;
+ case 20:
+ case SDLK_q:
+ //process recorderd buffer with low pass filter
+ if (current_state == RECORDED) {
+ convert_f32_to_double();
+ convert_double_to_f32();
+ }
+ break;
+ default:
+ printf("Unknown key %d\n",event.key.keysym.sym);
+ update_fractal = 1;
+ }
+ break;
+ }
+ }
+ //printf("Poll event\n");
+
+ }
+#if __EMSCRIPTEN__
+ if (current_state == RECORDING) {
+ SDL_LockAudioDevice( recordingDeviceId );
+ printf("recording=%d\n",audio_buf_position);
+ if( audio_buf_position > audio_rec_buffer_size )
+ {
+ //Stop recording audio
+ SDL_PauseAudioDevice( recordingDeviceId, SDL_TRUE );
+ current_state = RECORDED;
+ printf("State: RECORDED\n");
+ }
+
+ SDL_UnlockAudioDevice( recordingDeviceId );
+ } else if (current_state == PLAYBACK) {
+ SDL_LockAudioDevice( playbackDeviceId );
+ //Finished playback
+ if( audio_buf_position > audio_rec_buffer_size )
+ {
+ //Stop playing audio
+ SDL_PauseAudioDevice( playbackDeviceId, SDL_TRUE );
+ current_state = RECORDED;
+ printf("State: RECORDED\n");
+ }
+ //Unlock callback
+ SDL_UnlockAudioDevice( playbackDeviceId );
+ }
+#endif
+
+
+ //check for first ever run
+ if (first_run == 1)
+ {
+ first_run = 0;
+ update_fractal = 1;
+ }
+
+ if (update_fractal == 1)
+ {
+
+ }
+
+ #ifndef __EMSCRIPTEN__
+ if (update_fractal == 1)
+ #endif
+ {
+ SDL_GL_SwapWindow( window );
+ }
+ update_fractal=0;
+
+ tick_end = SDL_GetTicks();
+ if ((tick_end-tick_1sec)>1000) {
+ //perf_end = SDL_GetPerformanceCounter()-perf_start;
+ //tick_end = SDL_GetTicks()-tick_start;
+ //printf("FPS:%f\n",(1.0f/perf_end));
+ printf("FPS:%f\n",1.0f/((tick_end-tick_start)/1000.0f));
+ tick_1sec = tick_end;
+ }
+
+
+#if !__EMSCRIPTEN__
+ return 0;
+#endif
+}
+
+
+void main_loop()
+{
+ int i,count;
+ tick_1sec = SDL_GetTicks();
+#if __EMSCRIPTEN__
+ emscripten_set_main_loop(main_tick, 25, 1);
+#else
+ while (0 == quit)
+ {
+ main_tick();
+#if !__EMSCRIPTEN__
+ if (current_state == RECORDING) {
+ SDL_LockAudioDevice( recordingDeviceId );
+ printf("recording=%d\n",audio_buf_position);
+ if( audio_buf_position > audio_rec_buffer_size )
+ {
+ //Stop recording audio
+ SDL_PauseAudioDevice( recordingDeviceId, SDL_TRUE );
+ current_state = RECORDED;
+ printf("State: RECORDED\n");
+ }
+
+ SDL_UnlockAudioDevice( recordingDeviceId );
+ } else if (current_state == PLAYBACK) {
+ SDL_LockAudioDevice( playbackDeviceId );
+ //Finished playback
+ if( audio_buf_position > audio_rec_buffer_size )
+ {
+ //Stop playing audio
+ SDL_PauseAudioDevice( playbackDeviceId, SDL_TRUE );
+ current_state = RECORDED;
+ printf("State: RECORDED\n");
+ }
+ //Unlock callback
+ SDL_UnlockAudioDevice( playbackDeviceId );
+ }
+#endif
+ }
+#endif
+}
int main(int argc, const char * argv[]) {
+ int i,count;
// insert code here...
- printf("Hello, World!\n");
+ printf("Hello, World2!\n");
+ //if ( SDL_Init(SDL_INIT_EVERYTHING) < 0 )
+ if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 )
+ {
+ fprintf(stderr, "EXIT:Unable to init SDL: %s\n", SDL_GetError());
+ exit(1);
+ }
+
+
+
+ atexit(SDL_Quit);
+
+ printf("Prepare SDL2 window\n");
+ SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
+ SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
+ window = SDL_CreateWindow("KOH", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+ SDL_SetRenderDrawColor(renderer, 0xff, 0xaa, 0xaa, 0xaa);
+ SDL_GLContext gl_context = SDL_GL_CreateContext(window);
+ SDL_GL_SetSwapInterval( 0 );
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+
+ count = SDL_GetNumAudioDevices(0);
+ printf("Playback devices %d\n",count);
+ for (i=0;i<count;i++) {
+ printf("Playback audio device %d: %s\n", i, SDL_GetAudioDeviceName(i, 0));
+ }
+ count = SDL_GetNumAudioDevices(1);
+ printf("Recording devices %d\n",count);
+ for (i=0;i<count;i++) {
+ printf("Recording audio device %d: %s\n", i, SDL_GetAudioDeviceName(i, 1));
+ }
+
+ //https://github.com/emscripten-core/emscripten/issues/3477
+ //try whatever possible
+ SDL_AudioSpec audio_rec_want, audio_rec_have;
+ SDL_memset(&audio_rec_want, 0, sizeof(audio_rec_want)); /* or SDL_zero(want) */
+ audio_rec_want.freq = 48000;
+ audio_rec_want.format = AUDIO_F32;
+ audio_rec_want.channels = 2;
+ audio_rec_want.samples = 4096;
+ audio_rec_want.callback = audio_recording_callback;
+ recordingDeviceId = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(1, SDL_TRUE ), SDL_TRUE, &audio_rec_want, &audio_rec_have, SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
+
+ if (audio_rec_want.freq != audio_rec_have.freq) {
+ printf("Freq changed %d -> %d\n",audio_rec_want.freq,audio_rec_have.freq);
+ }
+
+ if (audio_rec_want.format != audio_rec_have.format) {
+ printf("Format changed %d -> %d\n",audio_rec_want.format, audio_rec_have.format);
+ }
+
+ if (recordingDeviceId == 0) {
+ printf("Failed to open recording device\n");
+ } else {
+ int byte_per_sample = audio_rec_have.channels * ( SDL_AUDIO_BITSIZE( audio_rec_have.format )/8);
+ int byte_per_second = audio_rec_have.freq * byte_per_sample;
+ printf("bytes per second %d\n",byte_per_second);
+ audio_rec_buffer_size = byte_per_second*RECORDING_BUFFER_SECONDS;
+ audio_rec_buffer_max_size = byte_per_second*MAX_RECORDING_SECONDS;
+ //audio_rec_buffer = malloc(audio_rec_buffer_max_size);
+ audio_rec_buffer = &audio_rec_buffer_[0];
+ printf("buffsize_max=%d\n",audio_rec_buffer_max_size);
+ printf("buffsize=%d\n",audio_rec_buffer_size);
+ memset(audio_rec_buffer,0,audio_rec_buffer_max_size);
+ }
+
+ SDL_AudioSpec audio_play_want, audio_play_have;
+ audio_play_want.freq = 48000;
+ audio_play_want.format = AUDIO_F32;
+ audio_play_want.channels = 2;
+ audio_play_want.samples = 4096;
+ audio_play_want.callback = audio_playback_callback;
+ playbackDeviceId = SDL_OpenAudioDevice(NULL, SDL_FALSE, &audio_play_want, &audio_play_have, SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
+
+ if (audio_play_want.freq != audio_play_have.freq) {
+ printf("Freq changed %d -> %d\n",audio_rec_want.freq,audio_rec_have.freq);
+ }
+
+ if (audio_play_want.format != audio_play_have.format) {
+ printf("Format changed %d -> %d\n",audio_play_want.format, audio_play_have.format);
+ }
+ current_state = STOPPED;
+ printf("State: STOPED\n");
+
+
+
+
+
+ //SDL_PauseAudioDevice(recordingDeviceId,0);
+ //!SDL_LockAudioDevice(recordingDeviceId);
+ //SDL_PauseAudioDevice(recordingDeviceId, 0);
+ //SDL_PauseAudio(0);
+ //SDL_Delay(4000);
+ //!SDL_UnlockAudioDevice(recordingDeviceId);
+ //!SDL_CloseAudio();
+ //SDL_CloseAudioDevice(recordingDeviceId);
+ /*
+ if (SDL_OpenAudio(&audio_want, &audio_have) < 0) {
+ SDL_Log("Failed to open audio: %s", SDL_GetError());
+ } else {
+ if (audio_have.format != audio_want.format) {
+ SDL_Log("We didn't get Float32 audio format.");
+ }
+ SDL_PauseAudio(0);
+ SDL_Delay(5000);
+ SDL_CloseAudio();
+ }
+ */
+
+ main_loop();
+
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_CloseAudio();//?
+ SDL_VideoQuit();//?
+ SDL_Quit();
+
return 0;
}