diff options
Diffstat (limited to 'WasmAudio')
-rw-r--r-- | WasmAudio/main.c | 389 |
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; } |