@@ -36,28 +36,94 @@ typedef struct {
3636 bool done;
3737 projectM::Settings settings;
3838 SDL_AudioDeviceID audioInputDevice;
39+
40+ // audio input device characteristics
41+ unsigned short audioChannelsCount;
42+ unsigned short audioSampleRate;
43+ unsigned short audioSampleCount;
44+ SDL_AudioFormat audioFormat;
45+ SDL_AudioDeviceID audioDeviceID;
46+ unsigned char *pcmBuffer; // pre-allocated buffer for audioInputCallback
3947} projectMApp;
4048
41- int selectAudioInput (projectMApp *app) {
42- // audio input stuff here is very platform-specific
43- // too bad the libsdl2 audio capture support doesn't exist
44-
45- #ifdef __APPLE__
46- // UInt32 audioInputIsAvailable;
47- // UInt32 propertySize = sizeof (audioInputIsAvailable);
48-
49- // AudioSessionGetProperty (
50- // kAudioSessionProperty_AudioInputAvailable,
51- // &propertySize,
52- // &audioInputIsAvailable // A nonzero value on output means that
53- // // audio input is available
54- // );
49+ void audioInputCallbackF32 (void *userdata, unsigned char *stream, int len) {
50+ // printf("LEN: %i\n", len);
51+ projectMApp *app = (projectMApp *) userdata;
52+ // stream is (i think) samples*channels floats (native byte order) of len BYTES
53+ app->pm ->pcm ()->addPCMfloat ((float *)stream, len/sizeof (float ));
54+ }
5555
56- #endif
56+ void audioInputCallbackS16 (void *userdata, unsigned char *stream, int len) {
57+ // printf("LEN: %i\n", len);
58+ projectMApp *app = (projectMApp *) userdata;
59+ short pcm16[2 ][512 ];
60+
61+ for (int i = 0 ; i < 512 ; i++) { //
62+ for (int j = 0 ; j < app->audioChannelsCount ; j++) {
63+ pcm16[j][i] = stream[i+j];
64+ }
65+ }
66+ app->pm ->pcm ()->addPCM16 (pcm16);
67+ }
68+
69+
70+ int openAudioInput (projectMApp *app) {
71+ // get audio input device
72+ int i, count = SDL_GetNumAudioDevices (true ); // capture, please
73+ if (count == 0 ) {
74+ SDL_LogCritical (SDL_LOG_CATEGORY_APPLICATION, " No audio capture devices found" );
75+ SDL_Quit ();
76+ }
77+ for (i = 0 ; i < count; i++) {
78+ SDL_Log (" Found audio capture device %d: %s" , i, SDL_GetAudioDeviceName (i, true ));
79+ }
80+
81+ // params for audio input
82+ SDL_AudioSpec want, have;
83+
84+ // TODO: let user somehow select audio input device
85+ SDL_AudioDeviceID selectedAudioDevice = 0 ; // hardcoded to use first device for now :/
86+
87+ // requested format
88+ SDL_zero (want);
89+ want.freq = 48000 ;
90+ want.format = AUDIO_F32; // float
91+ want.channels = 2 ;
92+ want.samples = 512 ;
93+ want.callback = audioInputCallbackF32;
94+ want.userdata = app;
95+
96+ app->audioDeviceID = SDL_OpenAudioDevice (SDL_GetAudioDeviceName (selectedAudioDevice, true ), true , &want, &have, 0 );
97+
98+ if (app->audioDeviceID == 0 ) {
99+ SDL_LogCritical (SDL_LOG_CATEGORY_APPLICATION, " Failed to open audio capture device: %s" , SDL_GetError ());
100+ SDL_Quit ();
101+ }
102+
103+ // read characteristics of opened capture device
104+ SDL_Log (" Opened audio capture device %i: %s" , app->audioDeviceID , SDL_GetAudioDeviceName (selectedAudioDevice, true ));
105+ SDL_Log (" Sample rate: %i, frequency: %i, channels: %i, format: %i" , have.samples , have.freq , have.channels , have.format );
106+ app->audioChannelsCount = have.channels ;
107+ app->audioSampleRate = have.freq ;
108+ app->audioSampleCount = have.samples ;
109+ app->audioFormat = have.format ;
57110
58111 return 1 ;
59112}
60113
114+ void beginAudioCapture (projectMApp *app) {
115+ // allocate a buffer to store PCM data for feeding in
116+ unsigned int maxSamples = app->audioChannelsCount * app->audioSampleCount ;
117+ app->pcmBuffer = (unsigned char *) malloc (maxSamples);
118+ SDL_PauseAudioDevice (app->audioDeviceID , false );
119+ // app->pm->pcm()->initPCM(maxSamples);
120+ }
121+
122+ void endAudioCapture (projectMApp *app) {
123+ free (app->pcmBuffer );
124+ SDL_PauseAudioDevice (app->audioDeviceID , true );
125+ }
126+
61127void keyHandler (projectMApp *app, SDL_Event *sdl_evt) {
62128 projectMEvent evt;
63129 projectMKeycode key;
@@ -74,38 +140,40 @@ void keyHandler(projectMApp *app, SDL_Event *sdl_evt) {
74140 }
75141}
76142
77- void renderFrame (projectMApp *app) {
143+ void addFakePCM (projectMApp *app) {
78144 int i;
79145 short pcm_data[2 ][512 ];
80- SDL_Event evt;
81-
82- SDL_PollEvent (&evt);
83- switch (evt.type ) {
84- case SDL_KEYDOWN:
85- keyHandler (app, &evt);
86- break ;
87- case SDL_QUIT:
88- app->done = true ;
89- break ;
90- }
91-
92146 /* * Produce some fake PCM data to stuff into projectM */
93147 for ( i = 0 ; i < 512 ; i++ ) {
94148 if ( i % 2 == 0 ) {
95149 pcm_data[0 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
96150 pcm_data[1 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
97- } else {
151+ } else {
98152 pcm_data[0 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
99153 pcm_data[1 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
100- }
154+ }
101155 if ( i % 2 == 1 ) {
102156 pcm_data[0 ][i] = -pcm_data[0 ][i];
103157 pcm_data[1 ][i] = -pcm_data[1 ][i];
104- }
158+ }
105159 }
106-
160+
107161 /* * Add the waveform data */
108162 app->pm ->pcm ()->addPCM16 (pcm_data);
163+ }
164+
165+ void renderFrame (projectMApp *app) {
166+ SDL_Event evt;
167+
168+ SDL_PollEvent (&evt);
169+ switch (evt.type ) {
170+ case SDL_KEYDOWN:
171+ keyHandler (app, &evt);
172+ break ;
173+ case SDL_QUIT:
174+ app->done = true ;
175+ break ;
176+ }
109177
110178 glClearColor ( 0.0 , 0.0 , 0.0 , 0.0 );
111179 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -123,21 +191,15 @@ int main( int argc, char *argv[] ) {
123191 int width = 784 ,
124192 height = 784 ;
125193
126- SDL_Init (SDL_INIT_VIDEO);
127-
128- // get an audio input device
129- if (! selectAudioInput (&app)) {
130- fprintf (stderr, " Failed to open audio input device\n " );
131- return 1 ;
132- }
194+ SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO);
133195
134196 app.win = SDL_CreateWindow (" projectM" , 0 , 0 , width, height, 0 );
135197 app.rend = SDL_CreateRenderer (app.win , 0 , SDL_RENDERER_ACCELERATED);
136198 if (! app.rend ) {
137199 fprintf (stderr, " Failed to create renderer: %s\n " , SDL_GetError ());
138200 return PROJECTM_ERROR;
139201 }
140- SDL_SetWindowTitle (app.win , " SDL Fun Party Time " );
202+ SDL_SetWindowTitle (app.win , " projectM Visualizer " );
141203 printf (" SDL init version 2\n " );
142204
143205 #ifdef PANTS
@@ -170,6 +232,10 @@ int main( int argc, char *argv[] ) {
170232 app.pm = new projectM (app.settings );
171233 app.pm ->selectRandom (true );
172234 app.pm ->projectM_resetGL (width, height);
235+
236+ // get an audio input device
237+ openAudioInput (&app);
238+ beginAudioCapture (&app);
173239
174240 // standard main loop
175241 const Uint32 frame_delay = 1000 /FPS;
0 commit comments