diff options
-rw-r--r-- | Build/Makefile | 5 | ||||
-rw-r--r-- | FIR/firmath.c | 247 | ||||
-rw-r--r-- | FIR/firmath.h | 43 | ||||
-rw-r--r-- | WasmAudio.xcodeproj/project.pbxproj | 52 | ||||
-rw-r--r-- | WasmAudio/main.c | 389 |
5 files changed, 729 insertions, 7 deletions
diff --git a/Build/Makefile b/Build/Makefile index 40d6a2e..6fe2da3 100644 --- a/Build/Makefile +++ b/Build/Makefile @@ -5,13 +5,12 @@ LDFLAGS=-lSDL2 -lSDL2_ttf EM_LDFALGS=-s USE_SDL=2 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s LLD_REPORT_UNDEFINED -s USE_GLFW=3 make: + $(CC) -c $(SOURCEDIR)/../FIR/firmath.c -g3 $(CC) -c $(SOURCEDIR)/main.c -g3 emcc: - $(EMCC) $(SOURCEDIR)/main.c -s WASM=1 -O3 -o index.js $(EM_LDFALGS) -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' + $(EMCC) $(SOURCEDIR)/main.c ../FIR/firmath.c -s WASM=1 -O3 -o index.js $(EM_LDFALGS) -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' - - web: darkhttpd ./ --port 12345 diff --git a/FIR/firmath.c b/FIR/firmath.c new file mode 100644 index 0000000..3fdf20b --- /dev/null +++ b/FIR/firmath.c @@ -0,0 +1,247 @@ +// +// firmath.c +// FIR_rect_win +// +// Created by Jacky Jack on 04/07/2021. +// + +#include "firmath.h" + +/* +void window_func_rect(double *w, int N1) { + int j; + + for (j=0;j<N1;j++) { + w[j] = 1.0; + } +} +*/ + +void fir_init(fir_t *fir, uint32_t taps) { + int i; + for (i=0;i<taps;i++) { + fir->fir_coef[i] = (double)0.0; + } + fir->num_taps = taps; +} + + +void firw_init(firw_t *fir_win, uint32_t taps) { + int i; + for (i=0;i<taps;i++) { + fir_win->win_coef[i] = (double)0.0; + } + fir_win->num_taps = taps; +} + + +double math_sinx(double x) { + if (x>-1.0E-5 && x < 1.0E-5) return (1.0); + return sin(x)/x; +} + +void fir_sinc_lp(fir_t *fir, double omega_c) { + int i; + double arg=0.0; + //should set 2fc?! + printf("omega_c=%f\n",omega_c); + for (i=0;i<fir->num_taps;i++) { + arg = (double)i-(double)(fir->num_taps-1)/2.0; + fir->fir_coef[i] = omega_c * math_sinx(omega_c*arg*M_PI); + } +} + +void fir_sinc_hp(fir_t *fir, double omega_c) { + int i; + double arg=0.0; + int even = fir->num_taps%2 ? 0: 1; + + //should set 2fc?! + printf("omega_c=%f\n",omega_c); + if (even) { + for (i=0;i<fir->num_taps;i++) { + arg = (double)i-(double)(fir->num_taps-1)/2.0; + if (arg == 0.0) { + fir->fir_coef[i] = 0.0; + } else { + //from IOWA + fir->fir_coef[i] = cos(omega_c*arg*M_PI)/M_PI/arg + cos(arg*M_PI); + } + } + } else { + for (i=0;i<fir->num_taps;i++) { + arg = (double)i-(double)(fir->num_taps-1)/2.0; + fir->fir_coef[i] = math_sinx(arg*M_PI)-omega_c * math_sinx(omega_c*arg*M_PI); + } + } +} + +void fir_sinc_bp(fir_t *fir, double omega_c1, double omega_c2) { + int i; + double arg=0.0; + //should set 2fc?! + printf("omega_c1=%f\n",omega_c1); + printf("omega_c2=%f\n",omega_c2); + for (i=0;i<fir->num_taps;i++) { + arg = (double)i-(double)(fir->num_taps-1)/2.0; + if (arg==0.0) { + fir->fir_coef[i] = 0.0; + } else { + //fir->fir_coef[i] = math_sinx(arg*M_PI) - omega_c2 * math_sinx(omega_c2*arg*M_PI) - omega_c1 * math_sinx(omega_c1*arg*M_PI); + fir->fir_coef[i] = (cos(omega_c1*arg*M_PI) - cos(omega_c2*arg*M_PI))/M_PI/arg; + } + } +} + +void fir_sinc_bs(fir_t *fir, double omega_c1, double omega_c2) { + int i; + double arg=0.0; + //should set 2fc?! + printf("omega_c1=%f\n",omega_c1); + printf("omega_c2=%f\n",omega_c2); + for (i=0;i<fir->num_taps;i++) { + arg = (double)i-(double)(fir->num_taps-1)/2.0; + if (arg==0.0) { + fir->fir_coef[i] = 0.0; + } else { + //fir->fir_coef[i] = math_sinx(arg*M_PI) - omega_c2 * math_sinx(omega_c2*arg*M_PI) - omega_c1 * math_sinx(omega_c1*arg*M_PI); + fir->fir_coef[i] = math_sinx(arg*M_PI) - omega_c2*math_sinx(omega_c2*arg*M_PI) - omega_c1*math_sinx(omega_c1*arg*M_PI); + } + } +} + +void fir_convolute(fir_t *fir,firw_t *firw) { + int i=0; + for (i=0;i<fir->num_taps;i++) { + fir->fir_coef[i] = fir->fir_coef[i]*firw->win_coef[i]; + } +} + + +void firw_rect(firw_t *fir_win) { + int i; + int n1 = fir_win->num_taps/2; + int even = fir_win->num_taps%2 ? 0: 1; + + if (even) n1+=1; + + for (i=0;i<n1;i++) { + fir_win->win_coef[i] = 1.0; + } + + for (i=0;i<n1;i++) { + fir_win->win_coef[fir_win->num_taps-1-i] = fir_win->win_coef[i]; + } + +} + + +void firw_hamming(firw_t *fir_win) { + int i; + double dN=0; + double arg=0; + //double p=0; + //double arg=0; + + int n1 = fir_win->num_taps/2; + int even = fir_win->num_taps%2 ? 0: 1; + if (!even) n1+=1; + dN = fir_win->num_taps +1; + + for (i=0;i<n1;i++) { + //arg = (double)i-(double)(fir_win->num_taps-1)/2.0; + //fir_win->win_coef[i] = 0.54+(1-0.54)*cos(2*M_PI*arg/n1); + + //fir_win->win_coef[i] = 0.54+(1-0.54)*cos(2*M_PI*i/n1); + arg = (double)i-(double)(fir_win->num_taps-1)/2.0; + fir_win->win_coef[i] = 0.54+0.46*cos(2*M_PI*arg/fir_win->num_taps); + + } + //fold + for (i=0;i<n1;i++) { + //arg = (double)i-(double)(fir_win->num_taps-1)/2.0; + //fir_win->win_coef[i] = 0.54+(1-0.54)*cos(2*M_PI*arg/n1); + + fir_win->win_coef[fir_win->num_taps-1-i] = fir_win->win_coef[i]; + } + +} + + +void firw_hanning(firw_t *fir_win) { + int i; + double dN=0; + double arg=0; + + int n1 = fir_win->num_taps/2; + int even = fir_win->num_taps%2 ? 0: 1; + if (!even) n1+=1; + dN = fir_win->num_taps +1; + + for (i=0;i<n1;i++) { + arg = (double)i-(double)(fir_win->num_taps-1)/2.0; + fir_win->win_coef[i] = 0.5+(1-0.5)*cos(2*M_PI*arg/fir_win->num_taps); + + } + //fold + for (i=0;i<n1;i++) { + fir_win->win_coef[fir_win->num_taps-1-i] = fir_win->win_coef[i]; + } +} + +void firw_blackman(firw_t *firw) { + int i; + double dN=0; + double arg=0; + + int n1 = firw->num_taps/2; + int even = firw->num_taps%2 ? 0: 1; + if (!even) n1+=1; + dN = firw->num_taps +1; + + for (i=0;i<n1;i++) { + arg = (double)i-(double)(firw->num_taps-1)/2.0; + /* + firw->win_coef[i] = 0.42 + +0.50*cos(2*M_PI*arg/(firw->num_taps)) + +0.08*cos(4*M_PI*arg/(firw->num_taps)); + */ + firw->win_coef[i] = 0.42 + +0.50*cos(2*M_PI*arg/(firw->num_taps-1)) + +0.08*cos(4*M_PI*arg/(firw->num_taps-1)); + + } + //fold + for (i=0;i<n1;i++) { + firw->win_coef[firw->num_taps-1-i] = firw->win_coef[i]; + } +} + +void fir_print_matlab(fir_t *fir) { + int i; + printf("f=[\n"); + for (i=0;i<fir->num_taps;i++) { + printf("%f\n",fir->fir_coef[i]); + } + printf("];\n"); +} + +void firw_print_matlab(firw_t *firw) { + int i; + printf("w=[\n"); + for (i=0;i<firw->num_taps;i++) { + printf("%f\n",firw->win_coef[i]); + } + printf("];\n"); +} + + +void fir_print_c(fir_t *fir) { + int i; + printf("double f=[\n"); + for (i=0;i<fir->num_taps;i++) { + printf("%f,\n",fir->fir_coef[i]); + } + printf("];\n"); +} + diff --git a/FIR/firmath.h b/FIR/firmath.h new file mode 100644 index 0000000..3540a98 --- /dev/null +++ b/FIR/firmath.h @@ -0,0 +1,43 @@ +// +// firmath.h +// FIR_rect_win +// +// Created by Jacky Jack on 04/07/2021. +// + +#ifndef firmath_h +#define firmath_h + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <math.h> + +typedef struct fir_t { + uint32_t num_taps; + double *fir_coef; +} fir_t; + +typedef struct firw_t { + uint32_t num_taps; + double *win_coef; +} firw_t; + +void fir_init(fir_t *fir, uint32_t taps); +void firw_init(firw_t *fir_win, uint32_t taps); + +double math_sinx(double x); +void fir_sinc_lp(fir_t *fir, double fc); +void fir_sinc_hp(fir_t *fir, double omega_c); +void fir_sinc_bp(fir_t *fir, double omega_c1, double omega_c2); +void fir_sinc_bs(fir_t *fir, double omega_c1, double omega_c2); +void fir_convolute(fir_t *fir,firw_t *fir_win); +void firw_rect(firw_t *firw); +void firw_hamming(firw_t *firw); +void firw_hanning(firw_t *firw); +void firw_blackman(firw_t *firw); +void fir_print_matlab(fir_t *fir); +void firw_print_matlab(firw_t *firw); +void fir_print_c(fir_t *fir); + +#endif /* firmath_h */ diff --git a/WasmAudio.xcodeproj/project.pbxproj b/WasmAudio.xcodeproj/project.pbxproj index 53e8a8c..4c87b7c 100644 --- a/WasmAudio.xcodeproj/project.pbxproj +++ b/WasmAudio.xcodeproj/project.pbxproj @@ -7,7 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 8D1ACB0726A0278200AAF1EB /* firmath.c in Sources */ = {isa = PBXBuildFile; fileRef = 8D1ACB0626A0278200AAF1EB /* firmath.c */; }; 8D6E30352694457C007D7ECF /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 8D6E30342694457C007D7ECF /* main.c */; }; + 8D6E303F269445E3007D7ECF /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D6E303E269445E2007D7ECF /* SDL2.framework */; }; + 8D6E30442694472D007D7ECF /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 8D6E30432694472D007D7ECF /* Makefile */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -23,8 +26,15 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 8D1ACB0526A0278200AAF1EB /* firmath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = firmath.h; sourceTree = "<group>"; }; + 8D1ACB0626A0278200AAF1EB /* firmath.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = firmath.c; sourceTree = "<group>"; }; 8D6E30312694457C007D7ECF /* WasmAudio */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = WasmAudio; sourceTree = BUILT_PRODUCTS_DIR; }; 8D6E30342694457C007D7ECF /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; }; + 8D6E303C269445C8007D7ECF /* Library */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Library; path = ../../../../../Library; sourceTree = "<group>"; }; + 8D6E303E269445E2007D7ECF /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../../Library/Frameworks/SDL2.framework; sourceTree = "<group>"; }; + 8D6E304026944620007D7ECF /* SDL2_ttf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2_ttf.framework; path = ../../../../../Library/Frameworks/SDL2_ttf.framework; sourceTree = "<group>"; }; + 8D6E30432694472D007D7ECF /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; }; + 8D6E304526944876007D7ECF /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = index.html; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -32,17 +42,30 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 8D6E303F269445E3007D7ECF /* SDL2.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 8D1ACB0426A0276B00AAF1EB /* FIR */ = { + isa = PBXGroup; + children = ( + 8D1ACB0626A0278200AAF1EB /* firmath.c */, + 8D1ACB0526A0278200AAF1EB /* firmath.h */, + ); + path = FIR; + sourceTree = "<group>"; + }; 8D6E30282694457C007D7ECF = { isa = PBXGroup; children = ( + 8D1ACB0426A0276B00AAF1EB /* FIR */, + 8D6E3042269446EE007D7ECF /* Build */, 8D6E30332694457C007D7ECF /* WasmAudio */, 8D6E30322694457C007D7ECF /* Products */, + 8D6E303B269445C8007D7ECF /* Frameworks */, ); sourceTree = "<group>"; }; @@ -62,6 +85,25 @@ path = WasmAudio; sourceTree = "<group>"; }; + 8D6E303B269445C8007D7ECF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8D6E304026944620007D7ECF /* SDL2_ttf.framework */, + 8D6E303E269445E2007D7ECF /* SDL2.framework */, + 8D6E303C269445C8007D7ECF /* Library */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 8D6E3042269446EE007D7ECF /* Build */ = { + isa = PBXGroup; + children = ( + 8D6E304526944876007D7ECF /* index.html */, + 8D6E30432694472D007D7ECF /* Makefile */, + ); + path = Build; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -118,6 +160,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8D1ACB0726A0278200AAF1EB /* firmath.c in Sources */, + 8D6E30442694472D007D7ECF /* Makefile in Sources */, 8D6E30352694457C007D7ECF /* main.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -240,6 +284,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(LOCAL_LIBRARY_DIR)/Frameworks", + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -248,6 +296,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(LOCAL_LIBRARY_DIR)/Frameworks", + ); PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; 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; } |