History

chost chust

Ge Wang committed 9 years ago

Commit 74cf4d41 parent 009ac193 files · +1596 −1506Browse files

Unified · Split

3 files
  1. src/host/chuck_audio.cpp +346 −1192
  2. src/host/chuck_audio.h +78 −304
  3. src/host/chuck_main.cpp +1172 −10
src/host/chuck_audio.cpp+346−1192
@@ -23,65 +23,31 @@ · 22 unmodified lines
2323 -----------------------------------------------------------------------------*/
2424
2525 //-----------------------------------------------------------------------------
26−// name: digiio_rtaudio.cpp
27−// desc: digitalio over RtAudio (from Gary Scavone)
26+// name: chuck_audio.cpp
27+// desc: chuck host digital audio I/O, using RtAudio
2828 //
2929 // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
3030 // Spencer Salazar (spencer@ccrma.stanford.edu)
3131 // RtAudio by: Gary Scavone
32−// date: Spring 2004
32+//
33+// date: Spring 2004 -- initial versions
34+// Fall 2017 -- REFACTOR-2017: clean up to be more modular
3335 //-----------------------------------------------------------------------------
34−#include "digiio_rtaudio.h"
35−#include "chuck_vm.h"
36+#include "chuck_audio.h"
3637 #include "chuck_errmsg.h"
3738 #include "chuck_globals.h"
3839 #include <limits.h>
39−#ifndef __DISABLE_RTAUDIO__
40−#include "RtAudio/RtAudio.h"
41−#endif // __DISABLE_RTAUDIO__
42−#if defined(__CHIP_MODE__)
43−#include "momu/mo_audio.h"
44−#endif // __CHIP_MODE__
45−#ifndef __DISABLE_MIDI__
4640 #include "rtmidi.h"
47−#endif // __DISABLE_MIDI__
48−// #include <signal.h>
41+
4942 #if (defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)) && !defined(__WINDOWS_PTHREAD__)
50−#include <windows.h>
51−#include <sys/timeb.h>
43+ #include <windows.h>
44+ #include <sys/timeb.h>
5245 #else
53−#include <unistd.h>
54−#include <sys/time.h>
46+ #include <unistd.h>
47+ #include <sys/time.h>
5548 #endif
5649
57−// extern "C" void signal_int( int );
58−
59−// static
60−BOOL__ Digitalio::m_init = FALSE;
61−DWORD__ Digitalio::m_start = 0;
62−DWORD__ Digitalio::m_tick_count = 0;
63−DWORD__ Digitalio::m_num_channels_out = NUM_CHANNELS_DEFAULT;
64−DWORD__ Digitalio::m_num_channels_in = NUM_CHANNELS_DEFAULT;
65−DWORD__ Digitalio::m_sampling_rate = SAMPLING_RATE_DEFAULT;
66−DWORD__ Digitalio::m_bps = BITS_PER_SAMPLE_DEFAULT;
67−DWORD__ Digitalio::m_buffer_size = BUFFER_SIZE_DEFAULT;
68−DWORD__ Digitalio::m_num_buffers = NUM_BUFFERS_DEFAULT;
69−RtAudio * Digitalio::m_rtaudio = NULL;
70−SAMPLE * Digitalio::m_buffer_out = NULL;
71−SAMPLE * Digitalio::m_buffer_in = NULL;
72−SAMPLE ** Digitalio::m_write_ptr = NULL;
73−SAMPLE ** Digitalio::m_read_ptr = NULL;
74−SAMPLE * Digitalio::m_extern_in = NULL;
75−SAMPLE * Digitalio::m_extern_out = NULL;
76−BOOL__ Digitalio::m_out_ready = FALSE;
77−BOOL__ Digitalio::m_in_ready = FALSE;
78−BOOL__ Digitalio::m_use_cb = USE_CB_DEFAULT;
79−DWORD__ Digitalio::m_go = 0;
80−DWORD__ Digitalio::m_dac_n = 0;
81−DWORD__ Digitalio::m_adc_n = 0;
82−DWORD__ Digitalio::m_end = 0;
83−DWORD__ Digitalio::m_block = TRUE;
84−DWORD__ Digitalio::m_xrun = 0;
50+
8551
8652
8753 // sample
@@ -94,7 +60,29 @@ DWORD__ Digitalio::m_xrun = 0; · 6 unmodified lines
9460
9561
9662
97−#ifndef __DISABLE_RTAUDIO__
63+// static initialization
64+t_CKBOOL ChuckAudio::m_init = FALSE;
65+t_CKBOOL ChuckAudio::m_start = FALSE;
66+t_CKBOOL ChuckAudio::m_go = FALSE;
67+t_CKBOOL ChuckAudio::m_silent = FALSE;
68+t_CKUINT ChuckAudio::m_num_channels_out = NUM_CHANNELS_DEFAULT;
69+t_CKUINT ChuckAudio::m_num_channels_in = NUM_CHANNELS_DEFAULT;
70+t_CKUINT ChuckAudio::m_sample_rate = SAMPLE_RATE_DEFAULT;
71+t_CKUINT ChuckAudio::m_buffer_size = BUFFER_SIZE_DEFAULT;
72+t_CKUINT ChuckAudio::m_num_buffers = NUM_BUFFERS_DEFAULT;
73+SAMPLE * ChuckAudio::m_buffer_out = NULL;
74+SAMPLE * ChuckAudio::m_buffer_in = NULL;
75+SAMPLE * ChuckAudio::m_extern_in = NULL;
76+SAMPLE * ChuckAudio::m_extern_out = NULL;
77+t_CKUINT ChuckAudio::m_dac_n = 0;
78+t_CKUINT ChuckAudio::m_adc_n = 0;
79+RtAudio * ChuckAudio::m_rtaudio = NULL;
80+f_audio_cb ChuckAudio::m_audio_cb = NULL;
81+void * ChuckAudio::m_cb_user_data = NULL;
82+
83+
84+
85+
9886 //-----------------------------------------------------------------------------
9987 // name: print()
10088 // desc: ...
@@ -134,7 +122,6 @@ void print( const RtAudio::DeviceInfo & info ) · 33 unmodified lines
134122 }
135123 }
136124 }
137−#endif // __DISABLE_RTAUDIO__
138125
139126
140127
@@ -143,14 +130,15 @@ void print( const RtAudio::DeviceInfo & info ) · 2 unmodified lines
143130 // name: probe()
144131 // desc: ...
145132 //-----------------------------------------------------------------------------
146−void Digitalio::probe()
133+void ChuckAudio::probe()
147134 {
148−#ifndef __DISABLE_RTAUDIO__
149− RtAudio * rta = NULL;
135+ // rtaduio pointer
136+ RtAudio * audio = NULL;
137+ // device info struct
150138 RtAudio::DeviceInfo info;
151139
152140 // allocate RtAudio
153− try { rta = new RtAudio( ); }
141+ try { audio = new RtAudio( ); }
154142 catch( RtError err )
155143 {
156144 // problem finding audio devices, most likely
@@ -158,17 +146,17 @@ void Digitalio::probe() · 1 unmodified line
158146 return;
159147 }
160148
161− // get count
162− int devices = rta->getDeviceCount();
149+ // get count
150+ int devices = audio->getDeviceCount();
163151 EM_error2b( 0, "found %d device(s) ...", devices );
164− // EM_error2( 0, "--------------------------" );
165−
152+
153+ // reset -- what does this do
166154 EM_reset_msg();
167155
168− // loop
156+ // loop over devices
169157 for( int i = 0; i < devices; i++ )
170158 {
171− try { info = rta->getDeviceInfo(i); }
159+ try { info = audio->getDeviceInfo(i); }
172160 catch( RtError & error )
173161 {
174162 error.printMessage();
@@ -181,11 +169,12 @@ void Digitalio::probe() · 6 unmodified lines
181169 // skip
182170 if( i < devices ) EM_error2( 0, "" );
183171
172+ // reset
184173 EM_reset_msg();
185174 }
186175
187− delete rta;
188−#endif // __DISABLE_RTAUDIO__
176+ // done
177+ SAFE_DELETE( audio );
189178
190179 return;
191180 }
@@ -195,16 +184,19 @@ void Digitalio::probe() · 3 unmodified lines
195184
196185 //-----------------------------------------------------------------------------
197186 // name: device_named()
198−// desc: ...
187+// desc: get device number by name; needs_dac/adc prompts further checks on
188+// requested device having > 0 channels
199189 //-----------------------------------------------------------------------------
200−DWORD__ Digitalio::device_named( const std::string & name, t_CKBOOL needs_dac, t_CKBOOL needs_adc )
190+t_CKUINT ChuckAudio::device_named( const std::string & name, t_CKBOOL needs_dac,
191+ t_CKBOOL needs_adc )
201192 {
202−#ifndef __DISABLE_RTAUDIO__
203− RtAudio * rta = NULL;
193+ // rtaudio pointer
194+ RtAudio * audio = NULL;
195+ // device info struct
204196 RtAudio::DeviceInfo info;
205197
206198 // allocate RtAudio
207− try { rta = new RtAudio( ); }
199+ try { audio = new RtAudio(); }
208200 catch( RtError err )
209201 {
210202 // problem finding audio devices, most likely
@@ -219,26 +211,30 @@ DWORD__ Digitalio::device_named( const std::string & name, t_CKBOOL needs_dac, t · 8 unmodified lines
219211 // loop
220212 for( int i = 0; i < devices; i++ )
221213 {
222− try { info = rta->getDeviceInfo(i); }
214+ // get info
215+ try { info = audio->getDeviceInfo(i); }
223216 catch( RtError & error )
224217 {
225218 error.printMessage();
226219 break;
227220 }
228−
221+
222+ // compare name
229223 if( info.name.compare(name) == 0 )
230224 {
225+ // found!
231226 device_no = i+1;
232227 break;
233228 }
234229 }
235230
231+ // not found, yet
236232 if( device_no == -1 )
237233 {
238234 // no exact match found; try partial match
239235 for( int i = 0; i < devices; i++ )
240236 {
241− try { info = rta->getDeviceInfo(i); }
237+ try { info = audio->getDeviceInfo(i); }
242238 catch( RtError & error )
243239 {
244240 error.printMessage();
@@ -247,9 +243,11 @@ DWORD__ Digitalio::device_named( const std::string & name, t_CKBOOL needs_dac, t · 2 unmodified lines
247243
248244 if( info.name.find(name) != std::string::npos )
249245 {
246+ // skip over ones with 0 channels, if needed
250247 if( (needs_dac && info.outputChannels == 0) ||
251248 (needs_adc && info.inputChannels == 0) )
252249 continue;
250+ // found
253251 device_no = i+1;
254252 break;
255253 }
@@ -257,65 +255,13 @@ DWORD__ Digitalio::device_named( const std::string & name, t_CKBOOL needs_dac, t · 1 unmodified line
257255 }
258256
259257 // clean up
260− SAFE_DELETE( rta );
258+ SAFE_DELETE( audio );
261259
262260 // done
263261 return device_no;
264−
265−#endif // __DISABLE_RTAUDIO__
266−
267− return -1;
268−}
269−
270−
271−
272−#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
273−//-----------------------------------------------------------------------------
274−// name: set_priority()
275−// desc: ...
276−//-----------------------------------------------------------------------------
277−static t_CKBOOL set_priority( CHUCK_THREAD tid, t_CKINT priority )
278−{
279− struct sched_param param;
280− int policy;
281−
282− // log
283− EM_log( CK_LOG_FINE, "setting thread priority to: %ld...", priority );
284−
285− // get for thread
286− if( pthread_getschedparam( tid, &policy, &param) )
287− return FALSE;
288−
289− // priority
290− param.sched_priority = priority;
291− // policy
292− policy = SCHED_RR;
293− // set for thread
294− if( pthread_setschedparam( tid, policy, &param ) )
295− return FALSE;
296−
297− return TRUE;
298262 }
299−#else
300−//-----------------------------------------------------------------------------
301−// name: set_priority()
302−// desc: ...
303−//-----------------------------------------------------------------------------
304−static t_CKBOOL set_priority( CHUCK_THREAD tid, t_CKINT priority )
305−{
306− // if priority is 0 then done
307− if( !priority ) return TRUE;
308−
309− // log
310− EM_log( CK_LOG_FINE, "setting thread priority to: %ld...", priority );
311263
312− // set the priority the thread
313− if( !SetThreadPriority( tid, priority ) )
314− return FALSE;
315264
316− return TRUE;
317−}
318−#endif
319265
320266
321267 //-----------------------------------------------------------------------------
@@ -333,11 +279,11 @@ static t_CKFLOAT get_current_time( t_CKBOOL fresh = TRUE ) · 11 unmodified lines
333279 if( fresh ) gettimeofday(&t,NULL);
334280 return t.tv_sec + (t_CKFLOAT)t.tv_usec/1000000;
335281 #endif
336−
337− return 0;
338282 }
339283
340284
285+
286+
341287 // watch dog globals
342288 static CHUCK_THREAD g_tid_synthesis = 0;
343289 static XThread * g_watchdog_thread = NULL;
@@ -345,9 +291,11 @@ static t_CKBOOL g_watchdog_state = FALSE; · 1 unmodified line
345291 static t_CKFLOAT g_watchdog_time = 0;
346292
347293
294+
295+
348296 //-----------------------------------------------------------------------------
349297 // name: watch_dog()
350−// desc: ...
298+// desc: this sniff out possible non-time advancing infinite loops
351299 //-----------------------------------------------------------------------------
352300 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
353301 static void * watch_dog( void * )
@@ -355,7 +303,8 @@ static void * watch_dog( void * ) · 1 unmodified line
355303 static unsigned int __stdcall watch_dog( void * )
356304 #endif
357305 {
358− t_CKFLOAT time;
306+ // time
307+ t_CKFLOAT time = 0;
359308
360309 // boost priority?
361310 t_CKUINT priority = Chuck_VM::our_priority;
@@ -371,43 +320,41 @@ static unsigned int __stdcall watch_dog( void * ) · 9 unmodified lines
371320 EM_poplog();
372321
373322 // boost watchdog by same priority
374− if( Chuck_VM::our_priority != 0x7fffffff )
375− Chuck_VM::set_priority( priority, NULL );
323+ if( XThreadUtil::our_priority != 0x7fffffff )
324+ XThreadUtil::set_priority( priority );
376325
377326 // while going
378327 while( g_do_watchdog )
379328 {
380329 // get
381330 time = get_current_time( TRUE );
382− // fprintf( stderr, "last: %f now: %f\n", g_watchdog_time, time );
331+ // CK_FPRINTF_STDERR( "last: %f now: %f\n", g_watchdog_time, time );
383332
384333 // resting
385334 if( g_watchdog_state == FALSE )
386335 {
387− // check xrun
388− // if( Digitalio::m_xrun > 100 )
336+ // check time vs timeout
389337 if( time - g_watchdog_time > g_watchdog_timeout )
390338 {
391339 // log
392340 EM_log( CK_LOG_SEVERE, "real-time watchdog counter-measure activating..." );
393341 // lowering priority
394− if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff )
395− set_priority( g_tid_synthesis, g_watchdog_countermeasure_priority );
342+ if( g_tid_synthesis && XThreadUtil::our_priority != 0x7fffffff )
343+ XThreadUtil::set_priority( g_tid_synthesis, g_watchdog_countermeasure_priority );
396344 // set state
397345 g_watchdog_state = TRUE;
398346 }
399347 }
400348 else
401349 {
402− // check xrun
403− // if( Digitalio::m_xrun == 0 )
350+ // check time vs timeout
404351 if( time - g_watchdog_time < g_watchdog_timeout )
405352 {
406353 // log
407354 EM_log( CK_LOG_SEVERE, "real-time watchdog resting..." );
408355 // raise priority
409− if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff )
410− set_priority( g_tid_synthesis, Chuck_VM::our_priority );
356+ if( g_tid_synthesis && XThreadUtil::our_priority != 0x7fffffff )
357+ XThreadUtil::set_priority( g_tid_synthesis, XThreadUtil::our_priority );
411358 // set state
412359 g_watchdog_state = FALSE;
413360 }
@@ -428,9 +375,9 @@ static unsigned int __stdcall watch_dog( void * ) · 14 unmodified lines
428375
429376 //-----------------------------------------------------------------------------
430377 // name: watchdog_start()
431−// desc: ...
378+// desc: start watchdog on separate thread
432379 //-----------------------------------------------------------------------------
433−BOOL__ Digitalio::watchdog_start()
380+t_CKBOOL ChuckAudio::watchdog_start()
434381 {
435382 // already
436383 if( g_watchdog_thread )
@@ -448,11 +395,12 @@ BOOL__ Digitalio::watchdog_start() · 11 unmodified lines
448395
449396
450397
398+
451399 //-----------------------------------------------------------------------------
452400 // name: watchdog_stop()
453−// desc: ...
401+// desc: stop watchdog thread
454402 //-----------------------------------------------------------------------------
455−BOOL__ Digitalio::watchdog_stop()
403+t_CKBOOL ChuckAudio::watchdog_stop()
456404 {
457405 // already
458406 if( !g_watchdog_thread )
@@ -460,8 +408,9 @@ BOOL__ Digitalio::watchdog_stop() · 1 unmodified line
460408
461409 // stop things
462410 g_do_watchdog = FALSE;
463− // wait a bit
464− // usleep( 100000 )
411+ // wait a bit | TODO: is this needed?
412+ usleep( 100000 )
413+ // delete watchdog thread | TODO: is this safe?
465414 SAFE_DELETE( g_watchdog_thread );
466415
467416 return TRUE;
@@ -474,369 +423,273 @@ BOOL__ Digitalio::watchdog_stop() · 6 unmodified lines
474423 // name: initialize()
475424 // desc: ...
476425 //-----------------------------------------------------------------------------
477−BOOL__ Digitalio::initialize( DWORD__ num_dac_channels,
478− DWORD__ num_adc_channels,
479− DWORD__ sampling_rate,
480− DWORD__ bps, DWORD__ buffer_size,
481− DWORD__ num_buffers, DWORD__ block,
482− Chuck_VM * vm_ref, BOOL__ rt_audio,
483− void * callback, void * data,
484− BOOL__ force_srate )
426+t_CKBOOL ChuckAudio::initialize( t_CKUINT num_dac_channels,
427+ t_CKUINT num_adc_channels,
428+ t_CKUINT sample_rate,
429+ t_CKUINT buffer_size,
430+ t_CKUINT num_buffers,
431+ f_audio_cb callback,
432+ void * data,
433+ t_CKBOOL force_srate )
485434 {
486435 if( m_init )
487436 return FALSE;
488437
489438 m_num_channels_out = num_dac_channels;
490439 m_num_channels_in = num_adc_channels;
491− m_sampling_rate = sampling_rate;
492− m_bps = bps;
440+ m_sample_rate = sample_rate;
493441 m_buffer_size = buffer_size;
494442 m_num_buffers = num_buffers;
495443 m_start = 0;
496− m_tick_count = 0;
497444 m_go = 0;
498− m_end = 0;
499− m_block = block;
500−
501− DWORD__ num_channels;
445+ m_silent = 0;
446+
447+ // remember callback
448+ m_audio_cb = callback;
449+ // remember user data to pass to callback
450+ m_cb_user_data = user_data;
451+
452+ // # of channels
453+ t_CKUINT num_channels = 0;
454+ // variable to pass by reference into RtAudio
502455 unsigned int bufsize = m_buffer_size;
503456
504457 // log
505458 EM_log( CK_LOG_FINE, "initializing RtAudio..." );
506459 // push indent
507460 EM_pushlog();
508−
509− // if rt_audio is false, then set block to FALSE to avoid deadlock
510− if( !rt_audio ) m_block = FALSE;
511461
512−#ifndef __DISABLE_RTAUDIO__
513− // if real-time audio
514− if( rt_audio )
462+ // allocate RtAudio
463+ try { m_rtaudio = new RtAudio( ); }
464+ catch( RtError err )
465+ {
466+ // problem finding audio devices, most likely
467+ EM_error2( 0, "%s", err.getMessage().c_str() );
468+ return m_init = FALSE;
469+ }
470+
471+ // convert 1-based ordinal to 0-based ordinal (added 1.3.0.0)
472+ // note: this is to preserve previous devices numbering after RtAudio change
473+ if( m_num_channels_out > 0 )
515474 {
516− // allocate RtAudio
517− try { m_rtaudio = new RtAudio( ); }
518− catch( RtError err )
475+ // check output device number; 0 used to mean "default"
476+ bool useDefault = ( m_dac_n == 0 );
477+ // default (refactor 1.3.1.2)
478+ if( useDefault )
519479 {
520− // problem finding audio devices, most likely
521− EM_error2( 0, "%s", err.getMessage().c_str() );
522− return m_init = FALSE;
480+ // get the default
481+ m_dac_n = m_rtaudio->getDefaultOutputDevice();
523482 }
524−
525− // convert 1-based ordinal to 0-based ordinal (added 1.3.0.0)
526− // note: this is to preserve previous devices numbering after RtAudio change
527− if( m_num_channels_out > 0 )
483+ else
528484 {
529− // check output device number; 0 used to mean "default"
530− bool useDefault = ( m_dac_n == 0 );
531−
532− // default (refactor 1.3.1.2)
533− if( useDefault )
534− {
535− // get the default
536− m_dac_n = m_rtaudio->getDefaultOutputDevice();
537− }
538− else
539− {
540− m_dac_n -= 1;
541− }
485+ m_dac_n -= 1;
486+ }
542487
543− // get device info
544− RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_dac_n);
545−
546− // ensure correct channel count if default device is requested
547− if( useDefault )
488+ // get device info
489+ RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_dac_n);
490+
491+ // ensure correct channel count if default device is requested
492+ if( useDefault )
493+ {
494+ // check
495+ if( device_info.outputChannels < m_num_channels_out )
548496 {
549− // check
550− if( device_info.outputChannels < m_num_channels_out )
497+ // find first device with at least the requested channel count
498+ m_dac_n = -1;
499+ int num_devices = m_rtaudio->getDeviceCount();
500+ for( int i = 0; i < num_devices; i++ )
551501 {
552− // find first device with at least the requested channel count
553− m_dac_n = -1;
554− int num_devices = m_rtaudio->getDeviceCount();
555− for( int i = 0; i < num_devices; i++ )
502+ device_info = m_rtaudio->getDeviceInfo(i);
503+ if(device_info.outputChannels >= m_num_channels_out)
556504 {
557− device_info = m_rtaudio->getDeviceInfo(i);
558− if(device_info.outputChannels >= m_num_channels_out)
559− {
560− m_dac_n = i;
561− break;
562− }
563− }
564−
565− // check for error
566− if( m_dac_n == -1 )
567− {
568− EM_error2( 0, "no audio output device with requested channel count (%i)...", m_num_channels_out );
569− return m_init = FALSE;
505+ m_dac_n = i;
506+ break;
570507 }
571508 }
509+
510+ // check for error
511+ if( m_dac_n == -1 )
512+ {
513+ EM_error2( 0, "no audio output device with requested channel count (%i)...",
514+ m_num_channels_out );
515+ return m_init = FALSE;
516+ }
572517 }
518+ }
573519
574− // index of closest sample rate
575− long closestIndex = -1;
576− // difference of closest so far
577− long closestDiff = LONG_MAX;
578− // the next highest
579− long nextHighest = -1;
580− // diff to next highest so far
581− long diffToNextHighest = LONG_MAX;
582− // check if request sample rate in support rates (added 1.3.1.2)
583− for( long i = 0; i < device_info.sampleRates.size(); i++ )
520+ // index of closest sample rate
521+ long closestIndex = -1;
522+ // difference of closest so far
523+ long closestDiff = LONG_MAX;
524+ // the next highest
525+ long nextHighest = -1;
526+ // diff to next highest so far
527+ long diffToNextHighest = LONG_MAX;
528+ // check if request sample rate in support rates (added 1.3.1.2)
529+ for( long i = 0; i < device_info.sampleRates.size(); i++ )
530+ {
531+ // difference
532+ long diff = device_info.sampleRates[i] - sampling_rate;
533+ // check // ge: changed from abs to labs, 2015.11
534+ if( ::labs(diff) < closestDiff )
584535 {
585− // difference
586− long diff = device_info.sampleRates[i] - sampling_rate;
587− // check // ge: changed from abs to labs, 2015.11
588− if( ::labs(diff) < closestDiff )
589− {
590− // remember index
591− closestIndex = i;
592− // update diff
593− closestDiff = ::labs(diff);
594− }
536+ // remember index
537+ closestIndex = i;
538+ // update diff
539+ closestDiff = ::labs(diff);
540+ }
595541
596− // for next highest
597− if( diff > 0 && diff < diffToNextHighest )
598− {
599− // remember index
600− nextHighest = i;
601− // update diff
602− diffToNextHighest = diff;
603− }
542+ // for next highest
543+ if( diff > 0 && diff < diffToNextHighest )
544+ {
545+ // remember index
546+ nextHighest = i;
547+ // update diff
548+ diffToNextHighest = diff;
604549 }
550+ }
605551
606− // see if we found exact match (added 1.3.1.2)
607− if( closestDiff != 0 )
552+ // see if we found exact match (added 1.3.1.2)
553+ if( closestDiff != 0 )
554+ {
555+ // check
556+ if( force_srate )
608557 {
609− // check
610− if( force_srate )
611− {
612− // request sample rate not found, error out
613− EM_error2( 0, "unsupported sample rate (%d) requested...", sampling_rate );
614− EM_error2( 0, "| (try --probe to enumerate available sample rates)" );
615− return m_init = FALSE;
616− }
558+ // request sample rate not found, error out
559+ EM_error2( 0, "unsupported sample rate (%d) requested...", sampling_rate );
560+ EM_error2( 0, "| (try --probe to enumerate available sample rates)" );
561+ return m_init = FALSE;
562+ }
617563
618− // use next highest if available
619− if( nextHighest >= 0 )
620− {
621− // log
622− EM_log( CK_LOG_SEVERE, "new sample rate (next highest): %d -> %d",
623− sampling_rate, device_info.sampleRates[nextHighest] );
624− // update sampling rate
625− m_sampling_rate = sampling_rate = device_info.sampleRates[nextHighest];
626− }
627− else if( closestIndex >= 0 ) // nothing higher
628− {
629− // log
630− EM_log( CK_LOG_SEVERE, "new sample rate (closest): %d -> %d",
631− sampling_rate, device_info.sampleRates[closestIndex] );
632− // update sampling rate
633− m_sampling_rate = sampling_rate = device_info.sampleRates[closestIndex];
634− }
635− else
636− {
637− // nothing to do (will fail and throw error message when opening)
638− }
564+ // use next highest if available
565+ if( nextHighest >= 0 )
566+ {
567+ // log
568+ EM_log( CK_LOG_SEVERE, "new sample rate (next highest): %d -> %d",
569+ sampling_rate, device_info.sampleRates[nextHighest] );
570+ // update sampling rate
571+ m_sampling_rate = sampling_rate = device_info.sampleRates[nextHighest];
572+ }
573+ else if( closestIndex >= 0 ) // nothing higher
574+ {
575+ // log
576+ EM_log( CK_LOG_SEVERE, "new sample rate (closest): %d -> %d",
577+ sampling_rate, device_info.sampleRates[closestIndex] );
578+ // update sampling rate
579+ m_sampling_rate = sampling_rate = device_info.sampleRates[closestIndex];
580+ }
581+ else
582+ {
583+ // nothing to do (will fail and throw error message when opening)
639584 }
640585 }
586+ }
641587
642− // convert 1-based ordinal to 0-based ordinal
643− if( m_num_channels_in > 0 )
588+ // convert 1-based ordinal to 0-based ordinal
589+ if( m_num_channels_in > 0 )
590+ {
591+ if( m_adc_n == 0 )
644592 {
645− if( m_adc_n == 0 )
593+ m_adc_n = m_rtaudio->getDefaultInputDevice();
594+
595+ // ensure correct channel count if default device is requested
596+ RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_adc_n);
597+
598+ // check if input channels > 0
599+ if( device_info.inputChannels < m_num_channels_in )
646600 {
647− m_adc_n = m_rtaudio->getDefaultInputDevice();
648−
649− // ensure correct channel count if default device is requested
650− RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_adc_n);
651−
652− // check if input channels > 0
653− if( device_info.inputChannels < m_num_channels_in )
601+ // find first device with at least the requested channel count
602+ m_adc_n = -1;
603+ int num_devices = m_rtaudio->getDeviceCount();
604+ for(int i = 0; i < num_devices; i++)
654605 {
655− // find first device with at least the requested channel count
656− m_adc_n = -1;
657− int num_devices = m_rtaudio->getDeviceCount();
658− for(int i = 0; i < num_devices; i++)
606+ device_info = m_rtaudio->getDeviceInfo(i);
607+ if(device_info.inputChannels >= m_num_channels_in)
659608 {
660− device_info = m_rtaudio->getDeviceInfo(i);
661− if(device_info.inputChannels >= m_num_channels_in)
662− {
663− m_adc_n = i;
664− break;
665− }
609+ m_adc_n = i;
610+ break;
666611 }
612+ }
667613
668− // changed 1.3.1.2 (ge): for input, if nothing found, we just gonna try to open half-duplex
669− if( m_adc_n == -1 )
670− {
671− // set to 0
672− m_num_channels_in = 0;
673− // problem finding audio devices, most likely
674− // EM_error2( 0, "unable to find audio input device with requested channel count (%i)...", m_num_channels_in);
675− // return m_init = FALSE;
676− }
614+ // changed 1.3.1.2 (ge): for input, if nothing found, we just gonna try to open half-duplex
615+ if( m_adc_n == -1 )
616+ {
617+ // set to 0
618+ m_num_channels_in = 0;
619+ // problem finding audio devices, most likely
620+ // EM_error2( 0, "unable to find audio input device with requested channel count (%i)...",
621+ // m_num_channels_in);
622+ // return m_init = FALSE;
677623 }
678624 }
679− else
680− {
681− m_adc_n -= 1;
682− }
683625 }
684−
685− // open device
686− try {
687− // log
688− EM_log( CK_LOG_FINE, "trying %d input %d output...",
689− m_num_channels_in, m_num_channels_out );
690−
691− RtAudio::StreamParameters output_parameters;
692− output_parameters.deviceId = m_dac_n;
693− output_parameters.nChannels = m_num_channels_out;
694− output_parameters.firstChannel = 0;
695−
696− RtAudio::StreamParameters input_parameters;
697− input_parameters.deviceId = m_adc_n;
698− input_parameters.nChannels = m_num_channels_in;
699− input_parameters.firstChannel = 0;
700−
701− RtAudio::StreamOptions stream_options;
702− stream_options.flags = 0;
703− stream_options.numberOfBuffers = num_buffers;
704− stream_options.streamName = "ChucK";
705− stream_options.priority = 0;
706−
707− // open RtAudio
708− m_rtaudio->openStream(
709− m_num_channels_out > 0 ? &output_parameters : NULL,
710− m_num_channels_in > 0 ? &input_parameters : NULL,
711− CK_RTAUDIO_FORMAT, sampling_rate, &bufsize,
712− m_use_cb ? ( block ? &cb : &cb2 ) : NULL, vm_ref,
713− &stream_options );
714− } catch( RtError err ) {
715− // log
716− EM_log( CK_LOG_INFO, "exception caught: '%s'...", err.getMessage().c_str() );
717− EM_error2( 0, "%s", err.getMessage().c_str() );
718− SAFE_DELETE( m_rtaudio );
719− return m_init = FALSE;
720− }
721−
722− // check bufsize
723− if( bufsize != (int)m_buffer_size )
626+ else
724627 {
725− EM_log( CK_LOG_SEVERE, "new buffer size: %d -> %i", m_buffer_size, bufsize );
726− m_buffer_size = bufsize;
628+ m_adc_n -= 1;
727629 }
728−
729− // pop indent
730− EM_poplog();
731− }
732−#endif // __DISABLE_RTAUDIO__
733−
734−#if defined(__CHIP_MODE__)
735− if( !MoAudio::init( sampling_rate, buffer_size, 2 ) )
736− {
737− EM_error2( 0, "%s", "(chuck)error: unable to initialize MoAudio..." );
738− return m_init = FALSE;
739630 }
740−#endif // __CHIP_MODE__
741631
742− if( m_use_cb )
743− {
744− num_channels = num_dac_channels > num_adc_channels ?
745− num_dac_channels : num_adc_channels;
632+ // open device
633+ try {
746634 // log
747− EM_log( CK_LOG_SEVERE, "allocating buffers for %d x %d samples...",
748− m_buffer_size, num_channels );
749− // allocate buffers
750− m_buffer_in = new SAMPLE[m_buffer_size * num_channels];
751− m_buffer_out = new SAMPLE[m_buffer_size * num_channels];
752− memset( m_buffer_in, 0, m_buffer_size * sizeof(SAMPLE) * num_channels );
753− memset( m_buffer_out, 0, m_buffer_size * sizeof(SAMPLE) * num_channels );
754− m_read_ptr = NULL;
755− m_write_ptr = NULL;
756− }
757−
758− m_in_ready = FALSE;
759− m_out_ready = FALSE;
635+ EM_log( CK_LOG_FINE, "trying %d input %d output...",
636+ m_num_channels_in, m_num_channels_out );
760637
761− return m_init = TRUE;
762−}
763−
764−
765−
766−
767−//-----------------------------------------------------------------------------
768−// name: cb()
769−// desc: ...
770−//-----------------------------------------------------------------------------
771−//int Digitalio::cb( char * buffer, int buffer_size, void * user_data )
772−int Digitalio::cb( void *output_buffer, void *input_buffer,
773− unsigned int buffer_size,
774− double streamTime,
775− RtAudioStreamStatus status,
776− void *user_data )
777−{
778− DWORD__ len = buffer_size * sizeof(SAMPLE) * m_num_channels_out;
779− DWORD__ n = 20;
780− DWORD__ start = 50;
781−
782− // copy input to local buffer
783− if( m_num_channels_in )
784− {
785− memcpy( m_buffer_in, input_buffer, len );
786− // copy to extern
787− if( m_extern_in ) memcpy( m_extern_in, input_buffer, len );
788− }
789− // flag ready
790− m_in_ready = TRUE;
791− // out is ready early
792− if( m_go < start && m_go > 1 && m_out_ready ) m_go = start;
793− // copy output into local buffer
794− if( m_go >= start )
795− {
796− while( !m_out_ready && n-- ) usleep( 250 );
797− if( m_out_ready && g_do_watchdog )
798− g_watchdog_time = get_current_time( TRUE );
799− // copy local buffer to be rendered
800− if( m_out_ready && !m_end ) memcpy( output_buffer, m_buffer_out, len );
801− // set all elements of local buffer to silence
802− else memset( output_buffer, 0, len );
638+ RtAudio::StreamParameters output_parameters;
639+ output_parameters.deviceId = m_dac_n;
640+ output_parameters.nChannels = m_num_channels_out;
641+ output_parameters.firstChannel = 0;
642+
643+ RtAudio::StreamParameters input_parameters;
644+ input_parameters.deviceId = m_adc_n;
645+ input_parameters.nChannels = m_num_channels_in;
646+ input_parameters.firstChannel = 0;
647+
648+ RtAudio::StreamOptions stream_options;
649+ stream_options.flags = 0;
650+ stream_options.numberOfBuffers = num_buffers;
651+ stream_options.streamName = "ChucK";
652+ stream_options.priority = 0;
653+
654+ // open RtAudio
655+ m_rtaudio->openStream(
656+ m_num_channels_out > 0 ? &output_parameters : NULL,
657+ m_num_channels_in > 0 ? &input_parameters : NULL,
658+ CK_RTAUDIO_FORMAT, sampling_rate, &bufsize,
659+ m_use_cb ? ( block ? &cb : &cb2 ) : NULL, vm_ref,
660+ &stream_options );
661+ } catch( RtError err ) {
662+ // log
663+ EM_log( CK_LOG_INFO, "exception caught: '%s'...", err.getMessage().c_str() );
664+ EM_error2( 0, "%s", err.getMessage().c_str() );
665+ SAFE_DELETE( m_rtaudio );
666+ return m_init = FALSE;
803667 }
804− else // initial condition
668+
669+ // check bufsize
670+ if( bufsize != (int)m_buffer_size )
805671 {
806− // priority boost
807− if( !m_go && Chuck_VM::our_priority != 0x7fffffff )
808− Chuck_VM::set_priority( Chuck_VM::our_priority, NULL );
809− // catch SIGINT
810− // signal( SIGINT, signal_int );
811−
812− // timestamp
813− if( g_do_watchdog ) g_watchdog_time = get_current_time( TRUE );
814−
815− memset( output_buffer, 0, len );
816− m_go++;
817− return 0;
672+ EM_log( CK_LOG_SEVERE, "new buffer size: %d -> %i", m_buffer_size, bufsize );
673+ m_buffer_size = bufsize;
818674 }
819675
820− // 2nd buffer
821− // RtAudio4 TODO
822−// if( m_go == start )
823−// {
824−// n = 8; while( !m_out_ready && n-- ) usleep( 250 );
825−// len /= sizeof(SAMPLE); DWORD__ i = 0;
826−// SAMPLE * s = (SAMPLE *) buffer;
827−// while( i < len ) *s++ *= (SAMPLE)i++/len;
828−// m_go++;
829−// }
676+ // pop indent
677+ EM_poplog();
830678
831− // copy to extern
832− if( m_extern_out ) memcpy( m_extern_out, output_buffer, len );
679+ // greater of dac/adc channels
680+ num_channels = num_dac_channels > num_adc_channels ?
681+ num_dac_channels : num_adc_channels;
682+ // log
683+ EM_log( CK_LOG_SEVERE, "allocating buffers for %d x %d samples...",
684+ m_buffer_size, num_channels );
833685
834− // set pointer to the beginning - if not ready, then too late anyway
835− //*m_write_ptr = (SAMPLE *)m_buffer_out;
836− //*m_read_ptr = (SAMPLE *)m_buffer_in;
837− m_out_ready = FALSE;
686+ // allocate buffers
687+ m_buffer_in = new SAMPLE[m_buffer_size * num_channels];
688+ m_buffer_out = new SAMPLE[m_buffer_size * num_channels];
689+ memset( m_buffer_in, 0, m_buffer_size * sizeof(SAMPLE) * num_channels );
690+ memset( m_buffer_out, 0, m_buffer_size * sizeof(SAMPLE) * num_channels );
838691
839− return 0;
692+ return m_init = TRUE;
840693 }
841694
842695
@@ -846,15 +699,11 @@ int Digitalio::cb( void *output_buffer, void *input_buffer, · 3 unmodified lines
846699 // name: cb2()
847700 // desc: ...
848701 //-----------------------------------------------------------------------------
849−//int Digitalio::cb2( char * buffer, int buffer_size, void * user_data )
850−int Digitalio::cb2( void *output_buffer, void *input_buffer,
851− unsigned int buffer_size,
852− double streamTime,
853− RtAudioStreamStatus status,
854− void *user_data )
702+int ChuckAudio::cb( void * output_buffer, void * input_buffer, unsigned int buffer_size,
703+ double streamTime, RtAudioStreamStatus status, void * user_data )
855704 {
856− DWORD__ len = buffer_size * sizeof(SAMPLE) * m_num_channels_out;
857− Chuck_VM * vm_ref = (Chuck_VM *)user_data;
705+ // length, in bytes of output
706+ t_CKUINT len = buffer_size * sizeof(SAMPLE) * m_num_channels_out;
858707
859708 // priority boost
860709 if( !m_go && Chuck_VM::our_priority != 0x7fffffff )
@@ -876,7 +725,7 @@ int Digitalio::cb2( void *output_buffer, void *input_buffer, · 15 unmodified lines
876725
877726 // TODO: close the duplicate handle?
878727 #endif
879− Chuck_VM::set_priority( Chuck_VM::our_priority, NULL );
728+ XThreadUtil::set_priority( XThreadUtil::our_priority );
880729 memset( output_buffer, 0, len );
881730 m_go = TRUE;
882731
@@ -901,21 +750,11 @@ int Digitalio::cb2( void *output_buffer, void *input_buffer, · 18 unmodified lines
901750 if( m_extern_in ) memcpy( m_extern_in, input_buffer, len );
902751 }
903752
904− // check xrun
905− if( m_xrun < 6 )
906− {
907− // timestamp
908− if( g_do_watchdog ) g_watchdog_time = get_current_time( TRUE );
909− // get samples from output
910− vm_ref->run( buffer_size, m_buffer_in, m_buffer_out );
911− // ...
912− if( m_xrun ) m_xrun--;
913− }
914− else
915− {
916− // reset
917− m_xrun /= 2;
918− }
753+ // timestamp
754+ if( g_do_watchdog ) g_watchdog_time = get_current_time( TRUE );
755+ // call the audio cb
756+ m_audio_cb( m_buffer_in, m_buffer_out, buffer_size,
757+ m_num_channels_in, m_num_channels_out, m_cb_user_data );
919758
920759 // copy local buffer to be rendered
921760 if( !m_end ) memcpy( output_buffer, m_buffer_out, len );
@@ -925,44 +764,27 @@ int Digitalio::cb2( void *output_buffer, void *input_buffer, · 3 unmodified lines
925764 // copy to extern
926765 if( m_extern_out ) memcpy( m_extern_out, output_buffer, len );
927766
928−
929767 return 0;
930768 }
931769
932770
933771
934772
935−#ifdef __CHIP_MODE__
936−//-----------------------------------------------------------------------------
937−// name: MoAudio_cb()
938−// desc: ...
939−//-----------------------------------------------------------------------------
940−void MoAudio_cb( Float32 * buffer, UInt32 numFrames, void * userData )
941−{
942− Digitalio::cb2( (char *)buffer, (char *)buffer, numFrames, 0, 0, userData );
943−}
944−#endif // __CHIP_MODE__
945−
946−
947−
948−
949773 //-----------------------------------------------------------------------------
950774 // name: start()
951−// desc: ...
775+// desc: start host audio
952776 //-----------------------------------------------------------------------------
953−BOOL__ Digitalio::start( )
777+t_CKBOOL ChuckAudio::start( )
954778 {
955−#ifndef __DISABLE_RTAUDIO__
956− try{ if( !m_start )
957− m_rtaudio->startStream();
958− m_start = TRUE;
959− } catch( RtError err ){ return FALSE; }
960−#endif // __DISABLE_RTAUDIO__
961−
962−#if defined(__CHIP_MODE__)
963− if( !m_start )
964− m_start = MoAudio::start( MoAudio_cb, g_vm );
965−#endif // __CHIP_MODE__
779+ try {
780+ if( !m_start )
781+ m_rtaudio->startStream();
782+ m_start = TRUE;
783+ }
784+ catch( RtError err )
785+ {
786+ return FALSE;
787+ }
966788
967789 return m_start;
968790 }
@@ -972,22 +794,22 @@ BOOL__ Digitalio::start( ) · 3 unmodified lines
972794
973795 //-----------------------------------------------------------------------------
974796 // name: stop()
975−// desc: ...
797+// desc: stop host audio
976798 //-----------------------------------------------------------------------------
977−BOOL__ Digitalio::stop( )
799+t_CKBOOL ChuckAudio::stop( )
978800 {
979−#ifndef __DISABLE_RTAUDIO__
980− try{ if( m_start )
981− m_rtaudio->stopStream();
982− m_start = FALSE;
983− } catch( RtError err ){ return FALSE; }
984−#endif // __DISABLE_RTAUDIO__
985−
986−#if defined(__CHIP_MODE__)
987− if( m_start )
988− MoAudio::stop();
989− m_start = FALSE;
990−#endif
801+ try {
802+ if( m_start )
803+ m_rtaudio->stopStream();
804+ m_start = FALSE;
805+ }
806+ catch( RtError err )
807+ {
808+ return FALSE;
809+ }
810+
811+ // REFACTOR-2017: set end flag
812+ m_silent = TRUE;
991813
992814 return !m_start;
993815 }
@@ -995,701 +817,33 @@ BOOL__ Digitalio::stop( ) · 1 unmodified line
995817
996818
997819
998−//-----------------------------------------------------------------------------
999−// name: tick()
1000−// desc: ...
1001−//-----------------------------------------------------------------------------
1002−//BOOL__ Digitalio::tick( )
1003−//{
1004−//#ifndef __DISABLE_RTAUDIO__
1005−// try
1006−// {
1007−// if( ++m_tick_count >= m_start )
1008−// {
1009−// m_rtaudio->tickStream();
1010−// m_tick_count = 0;
1011−// m_out_ready = TRUE;
1012−// m_in_ready = TRUE;
1013−// }
1014−//
1015−// return TRUE;
1016−// } catch( RtError err ){ return FALSE; }
1017−//#endif // __DISABLE_RTAUDIO__
1018−//
1019−// return FALSE;
1020−//}
1021−
1022−
1023−
1024−
1025820 //-----------------------------------------------------------------------------
1026821 // name: shutdown()
1027822 // desc: ...
1028823 //-----------------------------------------------------------------------------
1029−void Digitalio::shutdown()
824+void ChuckAudio::shutdown()
1030825 {
826+ // check flag
1031827 if( !m_init ) return;
1032828
1033−#ifndef __DISABLE_RTAUDIO__
829+ // stop watchdog | REFACTOR-2017: moved this earlier to give watchdog
830+ // a head start in stopping, to avoid unneeded countermeasure deployment
831+ watchdog_stop();
832+
833+ // check if started
1034834 if( m_start )
1035835 {
1036− //if( m_use_cb ) m_rtaudio->cancelStreamCallback();
1037− m_rtaudio->stopStream();
836+ // m_rtaudio->cancelStreamCallback();
837+ // m_rtaudio->stopStream();
838+ stop();
1038839 }
1039840
841+ // close stream
1040842 m_rtaudio->closeStream();
843+ // cleanup
1041844 SAFE_DELETE( m_rtaudio );
1042−#endif // __DISABLE_RTAUDIO__
1043845
846+ // unflag
1044847 m_init = FALSE;
1045848 m_start = FALSE;
1046−
1047− // stop watchdog
1048− watchdog_stop();
1049−}
1050−
1051−
1052−
1053−
1054−//-----------------------------------------------------------------------------
1055−// name: DigitalOut()
1056−// desc: ...
1057−//-----------------------------------------------------------------------------
1058−DigitalOut::DigitalOut()
1059−{
1060− m_data_ptr_out = NULL;
1061− m_data_max_out = NULL;
1062−}
1063−
1064−
1065−
1066−
1067−//-----------------------------------------------------------------------------
1068−// name: ~DigitalOut()
1069−// desc: ...
1070−//-----------------------------------------------------------------------------
1071−DigitalOut::~DigitalOut()
1072−{
1073− this->cleanup();
1074−}
1075−
1076−
1077−
1078−
1079−//-----------------------------------------------------------------------------
1080−// name: initialize()
1081−// desc: initialize audio out
1082−//-----------------------------------------------------------------------------
1083−BOOL__ DigitalOut::initialize( )
1084−{
1085−#ifndef __DISABLE_RTAUDIO__
1086− // set pointer to beginning of local buffer
1087− // RtAudio4 TODO
1088− m_data_ptr_out = Digitalio::m_use_cb ? Digitalio::m_buffer_out : NULL;
1089− // : (SAMPLE *)Digitalio::audio()->getStreamBuffer();
1090−#else
1091− // set pointer
1092− assert( Digitalio::m_use_cb );
1093− m_data_ptr_out = Digitalio::m_buffer_out;
1094−#endif // __DISABLE_RTAUDIO__
1095− // calculate the end of the buffer
1096− m_data_max_out = m_data_ptr_out +
1097− Digitalio::buffer_size() * Digitalio::num_channels_out();
1098− // set the writer pointer to our write pointer
1099− Digitalio::m_write_ptr = &m_data_ptr_out;
1100−
1101− return TRUE;
1102−}
1103−
1104−
1105−
1106−
1107−//-----------------------------------------------------------------------------
1108−// name: start()
1109−// desc: render
1110−//-----------------------------------------------------------------------------
1111−BOOL__ DigitalOut::start()
1112−{
1113− // start stream
1114− return ( Digitalio::start() != 0 );
1115−}
1116−
1117−
1118−
1119−
1120−//-----------------------------------------------------------------------------
1121−// name: stop()
1122−// desc: render
1123−//-----------------------------------------------------------------------------
1124−BOOL__ DigitalOut::stop()
1125−{
1126− // well
1127− Digitalio::stop();
1128−
1129− return TRUE;
1130−}
1131−
1132−
1133−
1134−
1135−//-----------------------------------------------------------------------------
1136−// name: cleanup()
1137−// desc: ...
1138−//-----------------------------------------------------------------------------
1139−void DigitalOut::cleanup()
1140−{
1141−}
1142−
1143−
1144−
1145−
1146−//-----------------------------------------------------------------------------
1147−// name: tick_out()
1148−// desc: 1 channel
1149−//-----------------------------------------------------------------------------
1150−BOOL__ DigitalOut::tick_out( SAMPLE sample )
1151−{
1152− if( !prepare_tick_out() )
1153− return FALSE;
1154−
1155− *m_data_ptr_out++ = sample;
1156−
1157− return TRUE;
1158−}
1159−
1160−
1161−
1162−
1163−//-----------------------------------------------------------------------------
1164−// name: tick_out()
1165−// desc: 2 channel
1166−//-----------------------------------------------------------------------------
1167−BOOL__ DigitalOut::tick_out( SAMPLE sample_l, SAMPLE sample_r )
1168−{
1169− if( !prepare_tick_out() )
1170− return FALSE;
1171−
1172− *m_data_ptr_out++ = sample_l;
1173− *m_data_ptr_out++ = sample_r;
1174−
1175− return TRUE;
1176−}
1177−
1178−
1179−
1180−
1181−//-----------------------------------------------------------------------------
1182−// name: tick_out()
1183−// desc: all channels
1184−//-----------------------------------------------------------------------------
1185−BOOL__ DigitalOut::tick_out( const SAMPLE * samples, DWORD__ n )
1186−{
1187− if( !prepare_tick_out() )
1188− return FALSE;
1189−
1190− if( !n ) n = Digitalio::m_num_channels_out;
1191− while( n-- )
1192− *m_data_ptr_out++ = *samples++;
1193−
1194− return TRUE;
1195−}
1196−
1197−
1198−
1199−
1200−//-----------------------------------------------------------------------------
1201−// name: prepare_tick_out()
1202−// desc: data ptr ok
1203−//-----------------------------------------------------------------------------
1204−inline BOOL__ DigitalOut::prepare_tick_out()
1205−{
1206− if( m_data_ptr_out >= m_data_max_out )
1207− {
1208− this->render();
1209− }
1210−
1211− return TRUE;
1212−}
1213−
1214−
1215−
1216−
1217−//-----------------------------------------------------------------------------
1218−// name: render()
1219−// desc: the render
1220−//-----------------------------------------------------------------------------
1221−DWORD__ DigitalOut::render()
1222−{
1223− //if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE;
1224−
1225− if( Digitalio::m_block )
1226− {
1227− // synchronize
1228− Digitalio::m_out_ready = TRUE;
1229− // synchronize
1230− while( Digitalio::m_out_ready )
1231− usleep( 250 );
1232− }
1233−
1234− // set pointer to the beginning - if not ready, then too late anyway
1235− *Digitalio::m_write_ptr = (SAMPLE *)Digitalio::m_buffer_out;
1236−
1237− return TRUE;
1238−}
1239−
1240−
1241−
1242−
1243−//-----------------------------------------------------------------------------
1244−// name: DigitalIn()
1245−// desc: ...
1246−//-----------------------------------------------------------------------------
1247−DigitalIn::DigitalIn()
1248−{
1249− m_data_ptr_in = NULL;
1250− m_data_max_in = NULL;
1251−}
1252−
1253−
1254−
1255−
1256−//-----------------------------------------------------------------------------
1257−// name: ~DigitalIn()
1258−// desc: ...
1259−//-----------------------------------------------------------------------------
1260−DigitalIn::~DigitalIn()
1261−{
1262− this->cleanup();
1263−}
1264−
1265−
1266−
1267−
1268−//-----------------------------------------------------------------------------
1269−// name: initialize()
1270−// desc: initialize audio in
1271−//-----------------------------------------------------------------------------
1272−BOOL__ DigitalIn::initialize( )
1273−{
1274− m_data = new SAMPLE[Digitalio::buffer_size() * Digitalio::num_channels_in()];
1275− memset( m_data, 0, Digitalio::buffer_size() * Digitalio::num_channels_in() * sizeof(SAMPLE) );
1276−#ifndef __DISABLE_RTAUDIO__
1277− // set the buffer to the beginning of the local buffer
1278− // RtAudio4 TODO
1279− m_data_ptr_in = Digitalio::m_use_cb ? m_data : NULL;
1280− // : (SAMPLE *)Digitalio::audio()->getStreamBuffer();
1281−#else
1282− // set the buffer pointer
1283− assert( Digitalio::m_use_cb );
1284− m_data_ptr_in = m_data;
1285−#endif // __DISABLE_RTAUDIO__
1286− // calculate past buffer
1287− m_data_max_in = m_data_ptr_in +
1288− Digitalio::buffer_size() * Digitalio::num_channels_in();
1289− // set the read pointer to the local pointer
1290− Digitalio::m_read_ptr = &m_data_ptr_in;
1291− // invalidate
1292− m_data_ptr_in = m_data_max_in;
1293−
1294− return TRUE;
1295−}
1296−
1297−
1298−
1299−
1300−//-----------------------------------------------------------------------------
1301−// name: start()
1302−// desc: ...
1303−//-----------------------------------------------------------------------------
1304−BOOL__ DigitalIn::start()
1305−{
1306− return ( Digitalio::start() != 0 );
1307−}
1308−
1309−
1310−
1311−
1312−//-----------------------------------------------------------------------------
1313−// name: capture_stop()
1314−// desc: ...
1315−//-----------------------------------------------------------------------------
1316−BOOL__ DigitalIn::stop()
1317−{
1318− Digitalio::stop();
1319− return TRUE;
1320−}
1321−
1322−
1323−
1324−
1325−//-----------------------------------------------------------------------------
1326−// name: cleanup()
1327−// desc: ...
1328−//-----------------------------------------------------------------------------
1329−void DigitalIn::cleanup()
1330−{
1331−}
1332−
1333−
1334−
1335−
1336−//-----------------------------------------------------------------------------
1337−// name: tick_in()
1338−// desc: ...
1339−//-----------------------------------------------------------------------------
1340−BOOL__ DigitalIn::tick_in( SAMPLE * s )
1341−{
1342− if( !prepare_tick_in() )
1343− return 0;
1344− *s = *m_data_ptr_in++;
1345−
1346− return TRUE;
1347−}
1348−
1349−
1350−
1351−
1352−//-----------------------------------------------------------------------------
1353−// name: tick_in()
1354−// desc: ...
1355−//-----------------------------------------------------------------------------
1356−BOOL__ DigitalIn::tick_in( SAMPLE * l, SAMPLE * r )
1357−{
1358− if( !prepare_tick_in() )
1359− return FALSE;
1360−
1361− *l = *m_data_ptr_in++;
1362− *r = *m_data_ptr_in++;
1363−
1364− return TRUE;
1365−}
1366−
1367−
1368−
1369−
1370−//-----------------------------------------------------------------------------
1371−// name: tick_in()
1372−// desc: ...
1373−//-----------------------------------------------------------------------------
1374−BOOL__ DigitalIn::tick_in( SAMPLE * sample, DWORD__ n )
1375−{
1376− if( !prepare_tick_in() )
1377− return FALSE;
1378−
1379− if( !n ) n = Digitalio::m_num_channels_in;
1380− while( n-- )
1381− *sample++ = *m_data_ptr_in++;
1382−
1383− return TRUE;
1384−}
1385−
1386−
1387−
1388−
1389−//-----------------------------------------------------------------------------
1390−// name: prepare_tick_in()
1391−// desc: data ptr ok
1392−//-----------------------------------------------------------------------------
1393−inline BOOL__ DigitalIn::prepare_tick_in()
1394−{
1395− if( m_data_ptr_in >= m_data_max_in )
1396− {
1397− this->capture();
1398− }
1399−
1400− return TRUE;
1401−}
1402−
1403−
1404−
1405−
1406−//-----------------------------------------------------------------------------
1407−// name: cb_capture()
1408−// desc: ...
1409−//-----------------------------------------------------------------------------
1410−DWORD__ DigitalIn::capture( )
1411−{
1412− // if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE;
1413−
1414− if( Digitalio::m_block )
1415− {
1416− t_CKUINT n = 20;
1417− while( !Digitalio::m_in_ready && n-- )
1418− usleep( 250 );
1419− }
1420−
1421− // copy data
1422− memcpy( m_data, Digitalio::m_buffer_in, Digitalio::buffer_size() *
1423− Digitalio::num_channels_in() * sizeof(SAMPLE) );
1424− Digitalio::m_in_ready = FALSE;
1425− // set pointer to the beginning - if not ready, then too late anyway
1426− *Digitalio::m_read_ptr = (SAMPLE *)m_data;
1427−
1428− return TRUE;
1429−}
1430−
1431−
1432−
1433−
1434−//-----------------------------------------------------------------------------
1435−// name: AudioBufferX()
1436−// desc: ...
1437−//-----------------------------------------------------------------------------
1438−AudioBufferX::AudioBufferX( DWORD__ size )
1439−{
1440− if( size )
1441− this->initialize( size );
1442− else
1443− {
1444− m_size = size;
1445− m_data = m_ptr_curr = m_ptr_end = NULL;
1446− }
1447−}
1448−
1449−
1450−
1451−
1452−//-----------------------------------------------------------------------------
1453−// name: initialize()
1454−// desc: ...
1455−//-----------------------------------------------------------------------------
1456−BOOL__ AudioBufferX::initialize( DWORD__ size )
1457−{
1458− m_size = size;
1459− m_data = (SAMPLE *)malloc( size * sizeof(SAMPLE) );
1460−
1461− if( !m_data )
1462− return FALSE;
1463−
1464− // clear the memory
1465− memset( m_data, 0, size * sizeof(SAMPLE) );
1466−
1467− // set the pointers
1468− m_ptr_curr = m_data;
1469− m_ptr_end = m_data + size;
1470−
1471− return TRUE;
1472−}
1473−
1474−
1475−
1476−
1477−//-----------------------------------------------------------------------------
1478−// name: cleanup()
1479−// desc: ...
1480−//-----------------------------------------------------------------------------
1481−void AudioBufferX::cleanup()
1482−{
1483− if( m_data )
1484− {
1485− free( m_data );
1486− m_data = NULL;
1487− }
1488−
1489− m_size = 0;
1490− m_ptr_curr = m_ptr_end = NULL;
1491−}
1492−
1493−
1494−
1495−
1496−//-----------------------------------------------------------------------------
1497−// name: size()
1498−// desc: ...
1499−//-----------------------------------------------------------------------------
1500−DWORD__ AudioBufferX::size()
1501−{
1502− return m_size;
1503−}
1504−
1505−
1506−
1507−
1508−//-----------------------------------------------------------------------------
1509−// name: data()
1510−// desc: ...
1511−//-----------------------------------------------------------------------------
1512−SAMPLE * AudioBufferX::data()
1513−{
1514− return m_data;
1515−}
1516−
1517−
1518−
1519−
1520−//-----------------------------------------------------------------------------
1521−// name: AudioBufferIn()
1522−// desc: ...
1523−//-----------------------------------------------------------------------------
1524−AudioBufferIn::AudioBufferIn( DWORD__ size )
1525− : AudioBufferX( size )
1526−{ }
1527−
1528−
1529−
1530−
1531−//-----------------------------------------------------------------------------
1532−// name: ~AudioBufferIn()
1533−// desc: ...
1534−//-----------------------------------------------------------------------------
1535−AudioBufferIn::~AudioBufferIn()
1536−{
1537− this->cleanup();
1538−}
1539−
1540−
1541−
1542−
1543−//-----------------------------------------------------------------------------
1544−// name: reset()
1545−// desc: ...
1546−//-----------------------------------------------------------------------------
1547−BOOL__ AudioBufferIn::reset()
1548−{
1549− m_ptr_curr = m_data;
1550−
1551− return TickIn::reset();
1552−}
1553−
1554−
1555−
1556−
1557−//-----------------------------------------------------------------------------
1558−// name: tick_in()
1559−// desc: ...
1560−//-----------------------------------------------------------------------------
1561−BOOL__ AudioBufferIn::tick_in( SAMPLE * s )
1562−{
1563− if( !m_data )
1564− return FALSE;
1565−
1566− *s = *m_ptr_curr++;
1567−
1568− return TRUE;
1569−}
1570−
1571−
1572−
1573−
1574−//-----------------------------------------------------------------------------
1575−// name: tick_in()
1576−// desc: ...
1577−//-----------------------------------------------------------------------------
1578−BOOL__ AudioBufferIn::tick_in( SAMPLE * l, SAMPLE * r )
1579−{
1580− if( !m_data || m_ptr_curr + 2 >= m_ptr_end )
1581− return FALSE;
1582−
1583− *l = *m_ptr_curr++;
1584− *r = *m_ptr_curr++;
1585−
1586− return TRUE;
1587−}
1588−
1589−
1590−
1591−
1592−//-----------------------------------------------------------------------------
1593−// name: tick_in()
1594−// desc: ...
1595−//-----------------------------------------------------------------------------
1596−BOOL__ AudioBufferIn::tick_in( SAMPLE * in, DWORD__ n )
1597−{
1598− if( !m_data || m_ptr_curr + n >= m_ptr_end )
1599− return FALSE;
1600−
1601− while( n-- )
1602− *in++ = *m_ptr_curr++;
1603−
1604− return TRUE;
1605−}
1606−
1607−
1608−
1609−
1610−//-----------------------------------------------------------------------------
1611−// name: AudioBufferOut()
1612−// desc: ...
1613−//-----------------------------------------------------------------------------
1614−AudioBufferOut::AudioBufferOut( DWORD__ size )
1615− : AudioBufferX( size )
1616−{ }
1617−
1618−
1619−
1620−
1621−//-----------------------------------------------------------------------------
1622−// name: ~AudioBufferOut()
1623−// desc: ...
1624−//-----------------------------------------------------------------------------
1625−AudioBufferOut::~AudioBufferOut()
1626−{
1627− this->cleanup();
1628−}
1629−
1630−
1631−
1632−
1633−//-----------------------------------------------------------------------------
1634−// name: reset()
1635−// desc: ...
1636−//-----------------------------------------------------------------------------
1637−BOOL__ AudioBufferOut::reset()
1638−{
1639− m_ptr_curr = m_data;
1640−
1641− return TickOut::reset();
1642−}
1643−
1644−
1645−
1646−
1647−//-----------------------------------------------------------------------------
1648−// name: tick_out()
1649−// desc: ...
1650−//-----------------------------------------------------------------------------
1651−BOOL__ AudioBufferOut::tick_out( SAMPLE s )
1652−{
1653− if( !m_data )
1654− return FALSE;
1655−
1656− *m_ptr_curr++ = s;
1657−
1658− return TRUE;
1659−}
1660−
1661−
1662−
1663−
1664−//-----------------------------------------------------------------------------
1665−// name: tick_out()
1666−// desc: ...
1667−//-----------------------------------------------------------------------------
1668−BOOL__ AudioBufferOut::tick_out( SAMPLE l, SAMPLE r )
1669−{
1670− if( !m_data || m_ptr_curr + 2 >= m_ptr_end )
1671− return FALSE;
1672−
1673− *m_ptr_curr++ = l;
1674− *m_ptr_curr++ = r;
1675−
1676− return TRUE;
1677−}
1678−
1679−
1680−
1681−
1682−//-----------------------------------------------------------------------------
1683−// name: tick_out()
1684−// desc: ...
1685−//-----------------------------------------------------------------------------
1686−BOOL__ AudioBufferOut::tick_out( const SAMPLE * out, DWORD__ n )
1687−{
1688− if( !m_data || m_ptr_curr + n >= m_ptr_end )
1689− return FALSE;
1690−
1691− while( n-- )
1692− *m_ptr_curr++ = *out++;
1693−
1694− return TRUE;
1695849 }
src/host/chuck_audio.h+78−304
@@ -23,351 +23,125 @@ · 22 unmodified lines
2323 -----------------------------------------------------------------------------*/
2424
2525 //-----------------------------------------------------------------------------
26−// name: digiio_rtaudio.h
27−// desc: digitalio over RtAudio (from Gary Scavone)
26+// name: chuck_audio.h
27+// desc: chuck host digital audio I/O, using RtAudio (from Gary Scavone)
2828 //
2929 // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
3030 // Spencer Salazar (spencer@ccrma.stanford.edu)
3131 // RtAudio by: Gary Scavone
3232 // date: Spring 2004
3333 //-----------------------------------------------------------------------------
34−#ifndef __DIGITAL_IO_H__
35−#define __DIGITAL_IO_H__
34+#ifndef __CHUCK_AUDIO_H__
35+#define __CHUCK_AUDIO_H__
3636
3737 #include "chuck_def.h"
3838 #include <string>
39−#ifndef __CHIP_MODE__
4039 #include "RtAudio/RtAudio.h"
41−#else
42−class RtAudio;
43−typedef unsigned int RtAudioStreamStatus;
44−#endif // __CHIP_MODE__
4540
4641
4742
4843
4944 //-----------------------------------------------------------------------------
50−// define and forward references
45+// define, defaults, forward references
5146 //-----------------------------------------------------------------------------
52−// #ifndef SAFE_DELETE
53−// #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
54−// #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
55−// #endif
56−
57−// defaults
58− #if defined(__MACOSX_CORE__)
59−#define BUFFER_SIZE_DEFAULT 256
60− #else
61−#define BUFFER_SIZE_DEFAULT 512
62− #endif
63−#define NUM_BUFFERS_DEFAULT 8
6447 #define NUM_CHANNELS_DEFAULT 2 // number of channels
65− #if defined(__PLATFORM_LINUX__)
66−#define SAMPLING_RATE_DEFAULT 48000 // sampling rate
67−#define USE_CB_DEFAULT TRUE // callback
68− #else
69−#define SAMPLING_RATE_DEFAULT 44100 // sampling rate
70−#define USE_CB_DEFAULT TRUE // callback
71− #endif
72−#define BITS_PER_SAMPLE_DEFAULT 16 // sample size
48+#define NUM_BUFFERS_DEFAULT 8 // number buffers
7349 #define DEVICE_NUM_OUT_DEFAULT 0
7450 #define DEVICE_NUM_IN_DEFAULT 0
51+// sample rate defaults by platform
52+#if defined(__PLATFORM_LINUX__)
53+#define SAMPLE_RATE_DEFAULT 48000
54+#define BUFFER_SIZE_DEFAULT 256
55+#else if defined(__PLATFORM_MACOSX__)
56+#define SAMPLE_RATE_DEFAULT 44100
57+#define BUFFER_SIZE_DEFAULT 256
58+#else
59+#define SAMPLE_RATE_DEFAULT 44100
60+#define BUFFER_SIZE_DEFAULT 512
61+#endif
7562
76−// sample types
77−// #define SAMPLE_SHORT short
78−// #define SAMPLE_INTERNAL SAMPLE_SHORT
79−// #define SAMPLE float
80−// #define S_MAX 0x7fff // max value for 16 bit
81−// #define S_MIN -0x7fff // min value for 16 bit
82−
83−// external to internal sample conversion
84−// #define SAMPLE_TO_INTERNAL(s) ( (SAMPLE_INTERNAL)((SAMPLE)S_MAX * s) )
85−// #define INTERNAL_TO_SAMPLE(s) ( (SAMPLE)((SAMPLE)s / S_MAX) )
86−
87−// types
88−#define BOOL__ DWORD__
89−#define DWORD__ unsigned long
90−#define SINT__ long
91−#define UINT__ DWORD__
92−#define BYTE__ unsigned char
9363
9464
95−#ifndef FALSE
96− #define FALSE 0
97−#endif
98−#ifndef TRUE
99− #define TRUE 1
100−#endif
10165
102−class RtAudio;
103−struct Chuck_VM;
66+// audio callback definition
67+void (* f_audio_cb)( SAMPLE * input, SAMPLE * output, t_CKUINT numFrames,
68+ t_CKUINT numInChans, t_CKUINT numOutChans, void * userData );
10469
10570
10671
10772
10873 //-----------------------------------------------------------------------------
109−// name: Digitalio
110−// desc: ...
74+// name: class ChuckAudio
75+// desc: chuck host audio I/O
11176 //-----------------------------------------------------------------------------
112−class Digitalio
77+class ChuckAudio
11378 {
11479 public:
115− static BOOL__ initialize( DWORD__ num_dac_channels,
116− DWORD__ num_adc_channels,
117− DWORD__ sampling_rate,
118− DWORD__ bps,
119− DWORD__ buffer_size,
120− DWORD__ num_buffers,
121− DWORD__ block,
122− Chuck_VM * vm_ref,
123− BOOL__ rt_audio,
124− void * callback,
125− void * data,
126− // force_srate added 1.3.1.2
127− BOOL__ force_srate );
128− static BOOL__ watchdog_start();
129− static BOOL__ watchdog_stop();
80+ static t_CKBOOL initialize( t_CKUINT num_dac_channels,
81+ t_CKUINT num_adc_channels,
82+ t_CKUINT sample_rate,
83+ t_CKUINT buffer_size,
84+ t_CKUINT num_buffers,
85+ f_audio_cb callback,
86+ void * data,
87+ // force_srate added 1.3.1.2
88+ t_CKBOOL force_srate );
13089 static void shutdown();
131− static void probe();
132−
133− static DWORD__ device_named( const std::string & name, t_CKBOOL needs_dac = FALSE, t_CKBOOL needs_adc = FALSE );
90+ static t_CKBOOL start();
91+ static t_CKBOOL stop();
13492
135−public:
136− static DWORD__ sampling_rate( ) { return m_sampling_rate; }
137− static DWORD__ num_channels_out( ) { return m_num_channels_out; }
138− static DWORD__ num_channels_in( ) { return m_num_channels_in; }
139− static DWORD__ dac_num( ) { return m_dac_n; }
140− static DWORD__ adc_num( ) { return m_adc_n; }
141− static DWORD__ bps( ) { return m_bps; }
142− static DWORD__ buffer_size( ) { return m_buffer_size; }
143− static DWORD__ num_buffers( ) { return m_num_buffers; }
144− static RtAudio * audio( ) { return m_rtaudio; }
145− static BOOL__ start( );
146− static BOOL__ stop( );
147− //static BOOL__ tick( );
148− static void set_extern( SAMPLE * in, SAMPLE * out )
149− { m_extern_in = in; m_extern_out = out; }
150− static int cb( void *output_buffer, void *input_buffer,
151− unsigned int buffer_size,
152− double streamTime,
153− RtAudioStreamStatus status,
154− void *user_data );
155− static int cb2( void *output_buffer, void *input_buffer,
156− unsigned int buffer_size,
157− double streamTime,
158− RtAudioStreamStatus status,
159− void *user_data );
93+public: // watchdog stuff
94+ static t_CKBOOL watchdog_start();
95+ static t_CKBOOL watchdog_stop();
96+
97+public: // device info
98+ // probe audio devices
99+ static void probe();
100+ // get device number by name?
101+ static t_CKUINT device_named( const std::string & name,
102+ t_CKBOOL needs_dac = FALSE,
103+ t_CKBOOL needs_adc = FALSE );
104+
105+public:
106+ static t_CKUINT srate() { return m_sample_rate; }
107+ static t_CKUINT num_channels_out() { return m_num_channels_out; }
108+ static t_CKUINT num_channels_in() { return m_num_channels_in; }
109+ static t_CKUINT dac_num() { return m_dac_n; }
110+ static t_CKUINT adc_num() { return m_adc_n; }
111+ static t_CKUINT bps() { return m_bps; }
112+ static t_CKUINT buffer_size() { return m_buffer_size; }
113+ static t_CKUINT num_buffers() { return m_num_buffers; }
114+ static RtAudio * audio() { return m_rtaudio; }
115+
116+ static void set_extern( SAMPLE * in, SAMPLE * out )
117+ { m_extern_in = in; m_extern_out = out; }
118+ static int cb( void * output_buffer, void * input_buffer, unsigned int buffer_size,
119+ double streamTime, RtAudioStreamStatus status, void * user_data );
160120
161121 public: // data
162− static BOOL__ m_init;
163− static DWORD__ m_start;
164− static DWORD__ m_tick_count;
165− static DWORD__ m_num_channels_out;
166− static DWORD__ m_num_channels_in;
167− static DWORD__ m_sampling_rate;
168− static DWORD__ m_bps;
169− static DWORD__ m_buffer_size;
170− static DWORD__ m_num_buffers;
171− static RtAudio * m_rtaudio;
122+ static t_CKBOOL m_init;
123+ static t_CKBOOL m_start;
124+ static t_CKBOOL m_go; // counter of # of times callback called
125+ static t_CKBOOL m_silent; // if true, will output silence
126+ static t_CKUINT m_num_channels_out;
127+ static t_CKUINT m_num_channels_in;
128+ static t_CKUINT m_sample_rate;
129+ static t_CKUINT m_bps;
130+ static t_CKUINT m_buffer_size;
131+ static t_CKUINT m_num_buffers;
172132 static SAMPLE * m_buffer_out;
173133 static SAMPLE * m_buffer_in;
174− static SAMPLE ** m_write_ptr;
175− static SAMPLE ** m_read_ptr;
176− static SAMPLE * m_extern_in;
177− static SAMPLE * m_extern_out;
178− static BOOL__ m_out_ready;
179− static BOOL__ m_in_ready;
180− static BOOL__ m_use_cb;
181− static DWORD__ m_go;
182− static DWORD__ m_end;
183− static DWORD__ m_block;
184− static DWORD__ m_xrun;
185−
186− static DWORD__ m_dac_n;
187− static DWORD__ m_adc_n;
188−};
189−
190−
191−
192−
193−//-----------------------------------------------------------------------------
194−// name: TickOut
195−// desc: ...
196−//-----------------------------------------------------------------------------
197−class TickOut
198−{
199−public:
200− virtual ~TickOut() {}
201−
202−public:
203− virtual BOOL__ reset() { return true; }
204− virtual BOOL__ tick_out( SAMPLE s ) = 0;
205− virtual BOOL__ tick_out( SAMPLE l, SAMPLE r ) = 0;
206− virtual BOOL__ tick_out( const SAMPLE * out, DWORD__ n ) = 0;
207−};
208−
209−
210−
211−
212−//-----------------------------------------------------------------------------
213−// name: TickIn
214−// desc: ...
215−//-----------------------------------------------------------------------------
216−class TickIn
217−{
218−public:
219− virtual ~TickIn() { }
220−
221−public:
222− virtual BOOL__ reset() { return true; }
223−
224− virtual BOOL__ tick_in( SAMPLE * in ) = 0;
225− virtual BOOL__ tick_in( SAMPLE * l, SAMPLE * r ) = 0;
226− virtual BOOL__ tick_in( SAMPLE * in, DWORD__ n ) = 0;
227−
228− virtual SAMPLE tick( )
229− { SAMPLE in; return ( tick_in( &in ) ? in : (SAMPLE)0.0f ); }
230−};
231−
232−
233−
234−
235−//-----------------------------------------------------------------------------
236−// name: class DigitalOut
237−// desc: ...
238−//-----------------------------------------------------------------------------
239−class DigitalOut : public TickOut
240−{
241−public:
242− DigitalOut();
243− ~DigitalOut();
244−
245−public:
246− BOOL__ initialize();
247− void cleanup();
248−
249− BOOL__ start();
250− BOOL__ stop();
251−
252−public:
253− virtual BOOL__ tick_out( SAMPLE s );
254− virtual BOOL__ tick_out( SAMPLE l, SAMPLE r );
255− virtual BOOL__ tick_out( const SAMPLE * samples, DWORD__ n );
256−
257−public:
258− DWORD__ render();
259−
260−protected:
261− SAMPLE * m_data_ptr_out;
262− SAMPLE * m_data_max_out;
134+ static SAMPLE * m_extern_in; // for things like audicle
135+ static SAMPLE * m_extern_out; // for things like audicle
263136
264− inline BOOL__ prepare_tick_out();
265−};
266−
267−
268−
269−
270−//-----------------------------------------------------------------------------
271−// name: class DigitalIn
272−// desc: ...
273−//-----------------------------------------------------------------------------
274−class DigitalIn : public TickIn
275−{
276−public:
277− DigitalIn();
278− ~DigitalIn();
279−
280−public: // in
281− BOOL__ initialize();
282− void cleanup();
283−
284− BOOL__ start();
285− BOOL__ stop();
286−
287−public:
288− virtual BOOL__ tick_in( SAMPLE * s );
289− virtual BOOL__ tick_in( SAMPLE * l, SAMPLE * r );
290− virtual BOOL__ tick_in( SAMPLE * samples, DWORD__ n );
291−
292−public:
293− DWORD__ capture( );
294−
295−protected:
296− SAMPLE * m_data;
297− SAMPLE * m_data_ptr_in;
298− SAMPLE * m_data_max_in;
299−
300− inline BOOL__ prepare_tick_in();
301−};
302−
303−
304−
305−
306−//-----------------------------------------------------------------------------
307−// name: AudioBufferX
308−// desc: ...
309−//-----------------------------------------------------------------------------
310−class AudioBufferX
311−{
312−public:
313− AudioBufferX( DWORD__ size = 0 );
314−
315−public:
316− BOOL__ initialize( DWORD__ size );
317− void cleanup();
318− SAMPLE * data();
319− DWORD__ size();
320−
321−protected:
322− SAMPLE * m_data;
323− DWORD__ m_size;
324−
325− SAMPLE * m_ptr_curr;
326− SAMPLE * m_ptr_end;
327−};
328−
329−
330−
331−
332−//-----------------------------------------------------------------------------
333−// name: AudioBufferIn
334−// desc: ...
335−//-----------------------------------------------------------------------------
336−class AudioBufferIn : public TickIn, public AudioBufferX
337−{
338−public:
339− AudioBufferIn( DWORD__ size = 0 );
340− virtual ~AudioBufferIn();
341−
342−public:
343− virtual BOOL__ reset();
344− virtual BOOL__ tick_in( SAMPLE * in );
345− virtual BOOL__ tick_in( SAMPLE * l, SAMPLE * r );
346− virtual BOOL__ tick_in( SAMPLE * in, DWORD__ n );
347−};
348−
349−
350−
351−
352−//-----------------------------------------------------------------------------
353−// name: AudioBufferOut
354−// desc: ...
355−//-----------------------------------------------------------------------------
356−class AudioBufferOut : public TickOut, public AudioBufferX
357−{
358−public:
359− AudioBufferOut( DWORD__ size = 0 );
360− virtual ~AudioBufferOut();
361−
362−public:
363− virtual BOOL__ reset();
364− virtual BOOL__ tick_out( SAMPLE s );
365− virtual BOOL__ tick_out( SAMPLE l, SAMPLE r );
366− virtual BOOL__ tick_out( const SAMPLE * out, DWORD__ n );
137+ static RtAudio * m_rtaudio;
138+ static t_CKUINT m_dac_n;
139+ static t_CKUINT m_adc_n;
140+ static f_audio_cb m_audio_cb;
141+ static void * m_cb_user_data;
367142 };
368143
369144
370145
371146
372147 #endif
373−
src/host/chuck_main.cpp+1172−10
@@ -24,25 +24,1187 @@ · 23 unmodified lines
2424
2525 //-----------------------------------------------------------------------------
2626 // file: chuck_main.cpp
27−// desc: chuck entry point
27+// desc: chuck entry point | command line host
2828 //
2929 // v1.3.5.3: migration to chuck_system.* (see for more details)
3030 //
31−// author: Ge Wang (http://www.gewang.com/)
31+// author: Ge Wang | http://www.gewang.com/
3232 // (see chuck_system.*)
3333 //-----------------------------------------------------------------------------
34−#include "chuck_system.h"
34+#include "chuck.h"
35+#include "chuck_audio.h"
3536
36−#ifndef __ALTER_ENTRY_POINT__
37−int main( int argc, const char ** argv )
37+
38+
39+
40+// function prototypes
41+t_CKBOOL init_shell( Chuck_Shell * shell, Chuck_Shell_UI * ui, Chuck_VM * vm );
42+void global_cleanup();
43+void usage();
44+void uh();
45+t_CKBOOL get_count( const char * arg, t_CKUINT * out );
46+void cb( t_CKSAMPLE * in, t_CKSAMPLE * out, t_CKUINT numFrames,
47+ t_CKUINT numInChans, t_CKUINT numOutChans, void * data );
48+
49+// C functions
50+extern "C" void signal_int( int sig_num );
51+
52+
53+// the one ChucK, for command line host
54+ChucK * the_chuck;
55+// thread id for shell
56+CHUCK_THREAD g_tid_shell = 0;
57+// default destination host name
58+char g_otf_dest[256] = "127.0.0.1";
59+
60+// the shell
61+Chuck_Shell * g_shell = NULL;
62+// global variables
63+t_CKUINT g_sigpipe_mode = 0;
64+// real-time watch dog
65+t_CKBOOL g_do_watchdog = FALSE;
66+// countermeasure
67+#ifdef __MACOSX_CORE__
68+t_CKUINT g_watchdog_countermeasure_priority = 10;
69+#elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__)
70+t_CKUINT g_watchdog_countermeasure_priority = THREAD_PRIORITY_LOWEST;
3871 #else
39−extern "C" int chuck_main( int argc, const char ** argv )
72+t_CKUINT g_watchdog_countermeasure_priority = 0;
4073 #endif
74+// watchdog timeout
75+t_CKFLOAT g_watchdog_timeout = 0.5;
76+// thread id for whatever
77+CHUCK_THREAD g_tid_whatever = 0;
78+// flag for Std.system( string )
79+t_CKBOOL g_enable_system_cmd = FALSE;
80+// flag for enabling shell, ge: 1.3.5.3
81+t_CKBOOL g_enable_shell = FALSE;
82+// flag for audio enable, ge: 1.3.5.3
83+t_CKBOOL g_enable_realtime_audio = TRUE;
84+// added 1.3.2.0 // moved from VM 1.3.5.3
85+f_mainthreadhook g_main_thread_hook = NULL;
86+f_mainthreadquit g_main_thread_quit = NULL;
87+void * g_main_thread_bindle = NULL;
88+// num vms running; used to quit le_cb thread // added 1.3.6.0
89+t_CKUINT g_num_vms_running = 0;
90+
91+
92+
93+
94+//-----------------------------------------------------------------------------
95+// name: main()
96+// desc: ...
97+//-----------------------------------------------------------------------------
98+int main( int argc, const char ** argv )
4199 {
42− // chuck system
43− Chuck_System chuck;
44− // do it
45− chuck.go( argc, argv );
100+ // parse, init, run!
101+ go( argc, argv );
102+
103+ // clean up
104+ global_cleanup();
46105
47106 return 0;
48107 }
108+
109+
110+
111+
112+//-----------------------------------------------------------------------------
113+// name: cb()
114+// desc: audio callback
115+//-----------------------------------------------------------------------------
116+void cb( t_CKSAMPLE * in, t_CKSAMPLE * out, t_CKUINT numFrames,
117+ t_CKUINT numInChans, t_CKUINT numOutChans, void * data )
118+{
119+ // TODO: check channel numbers
120+
121+ // call up to ChucK
122+ the_chuck->run( in, out, numFrames );
123+}
124+
125+
126+
127+
128+//-----------------------------------------------------------------------------
129+// name: version()
130+// desc: ...
131+//-----------------------------------------------------------------------------
132+static void version()
133+{
134+ CK_FPRINTF_STDERR( "\n" );
135+ CK_FPRINTF_STDERR( "chuck version: %s\n", ChucK::version() );
136+
137+ // platform string
138+ string platform = "";
139+
140+#if defined(__PLATFORM_WIN32__)
141+ platform = "microsoft win32";
142+#elif defined(__WINDOWS_DS__)
143+ platform = "microsoft win32 + cygwin";
144+#elif defined(__LINUX_ALSA__)
145+ platform = "linux (alsa)";
146+#elif defined(__LINUX_OSS__)
147+ platform = "linux (oss)";
148+#elif defined(__LINUX_JACK__) || defined(__UNIX_JACK__)
149+ platform = "linux (jack)";
150+#elif defined(__LINUX_PULSE__)
151+ platform = "linux (pulse)";
152+#elif defined(__MACOSX_UB__)
153+ platform = "mac os x : universal binary";
154+#elif defined(__MACOSX_CORE__) && defined(__LITTLE_ENDIAN__)
155+ platform = "mac os x : intel";
156+#elif defined(__MACOSX_CORE__)
157+ platform = "mac os x : powerpc";
158+#else
159+ platform = "uh... unknown";
160+#endif
161+
162+ CK_FPRINTF_STDERR( " %s : %ld-bit\n", platform.c_str(), machine_intsize() );
163+ CK_FPRINTF_STDERR( " http://chuck.cs.princeton.edu/\n" );
164+ CK_FPRINTF_STDERR( " http://chuck.stanford.edu/\n\n" );
165+}
166+
167+
168+
169+//-----------------------------------------------------------------------------
170+// name: usage()
171+// desc: ...
172+//-----------------------------------------------------------------------------
173+static void usage()
174+{
175+ // (note: optional colon added 1.3.0.0)
176+ CK_FPRINTF_STDERR( "usage: chuck --[options|commands] [+-=^] file1 file2 file3 ...\n" );
177+ CK_FPRINTF_STDERR( " [options] = halt|loop|audio|silent|dump|nodump|server|about|probe|\n" );
178+ CK_FPRINTF_STDERR( " channels:<N>|out:<N>|in:<N>|dac:<N>|adc:<N>|\n" );
179+ CK_FPRINTF_STDERR( " srate:<N>|bufsize:<N>|bufnum:<N>|shell|empty|\n" );
180+ CK_FPRINTF_STDERR( " remote:<hostname>|port:<N>|verbose:<N>|level:<N>|\n" );
181+ CK_FPRINTF_STDERR( " callback|deprecate:{stop|warn|ignore}|\n" );
182+ CK_FPRINTF_STDERR( " chugin-load:{auto|off}|chugin-path:<path>|chugin:<name>\n" );
183+ CK_FPRINTF_STDERR( " [commands] = add|remove|replace|remove.all|status|time|kill\n" );
184+ CK_FPRINTF_STDERR( " [+-=^] = shortcuts for add, remove, replace, status\n" );
185+ version();
186+}
187+
188+
189+
190+
191+//-----------------------------------------------------------------------------
192+// name: get_count()
193+// desc: get the thing after -- or - as number
194+//-----------------------------------------------------------------------------
195+static t_CKBOOL get_count( const char * arg, t_CKUINT * out )
196+{
197+ // no comment
198+ if( !strncmp( arg, "--", 2 ) ) arg += 2;
199+ else if( !strncmp( arg, "-", 1 ) ) arg += 1;
200+ else return FALSE;
201+
202+ // end of string
203+ if( *arg == '\0' ) return FALSE;
204+ // not digit
205+ if( *arg < '0' || *arg > '9' ) return FALSE;
206+
207+ // number
208+ *out = (t_CKUINT)atoi( arg );
209+
210+ return TRUE;
211+}
212+
213+
214+
215+
216+//-----------------------------------------------------------------------------
217+// name: signal_int()
218+// desc: ...
219+//-----------------------------------------------------------------------------
220+extern "C" void signal_int( int sig_num )
221+{
222+ // log
223+ CK_FPRINTF_STDERR( "[chuck]: cleaning up...\n" );
224+ // clean up everything!
225+ global_cleanup();
226+ // exit with code
227+ exit( 130 ); // 130 -> terminated by ctrl-c
228+}
229+
230+
231+
232+
233+//-----------------------------------------------------------------------------
234+// name: global_cleanup()
235+// desc: ...
236+//-----------------------------------------------------------------------------
237+void global_cleanup()
238+{
239+ // if any Chuck_Systems are left, delete them
240+ while( !g_systems.empty() )
241+ {
242+ Chuck_System * next_chuck = g_systems.front();
243+ // delete Chuck_System causes a g_systems.remove which modifies the list
244+ // and thus g_systems.front() will be different next time
245+ delete next_chuck;
246+ }
247+
248+ // request bbq shutdown
249+ all_stop();
250+
251+ // request MIDI, etc. files open be closed
252+ all_detach();
253+
254+ // shutdown audio
255+ if( g_enable_realtime_audio )
256+ {
257+ // log
258+ EM_log( CK_LOG_SYSTEM, "shutting down real-time audio..." );
259+
260+ g_bbq->digi_out()->cleanup();
261+ g_bbq->digi_in()->cleanup();
262+ g_bbq->shutdown();
263+ // m_audio = FALSE;
264+ }
265+ // log
266+ EM_log( CK_LOG_SYSTEM, "freeing bbq subsystem..." );
267+ // clean up
268+ SAFE_DELETE( g_bbq );
269+
270+ if( g_main_thread_quit )
271+ g_main_thread_quit( g_main_thread_bindle );
272+ clear_main_thread_hook();
273+
274+ // wait for the shell, if it is running
275+ // does the VM reset its priority to normal before exiting?
276+ if( g_enable_shell )
277+ while( g_shell != NULL )
278+ usleep(10000);
279+
280+ // things don't work so good on windows...
281+#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
282+ // pthread_kill( g_tid_otf, 2 );
283+ if( g_tid_otf ) pthread_cancel( g_tid_otf );
284+ if( g_tid_whatever ) pthread_cancel( g_tid_whatever );
285+ // if( g_tid_otf ) usleep( 50000 );
286+#else
287+ // close handle
288+ if( g_tid_otf ) CloseHandle( g_tid_otf );
289+#endif
290+
291+ // ck_close( g_sock );
292+
293+#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
294+ // pthread_join( g_tid_otf, NULL );
295+#endif
296+}
297+
298+
299+
300+
301+//-----------------------------------------------------------------------------
302+// name: init_shell()
303+// desc: ...
304+//-----------------------------------------------------------------------------
305+static t_CKBOOL init_shell( Chuck_Shell * shell, Chuck_Shell_UI * ui, Chuck_VM * vm )
306+{
307+ // initialize shell UI
308+ if( !ui->init() )
309+ {
310+ CK_FPRINTF_STDERR( "[chuck]: error starting shell UI...\n" );
311+ return FALSE;
312+ }
313+
314+ // initialize
315+ if( !shell->init( vm, ui ) )
316+ {
317+ CK_FPRINTF_STDERR( "[chuck]: error starting shell...\n" );
318+ return FALSE;
319+ }
320+
321+ return TRUE;
322+}
323+
324+
325+
326+
327+//-----------------------------------------------------------------------------
328+// name: go()
329+// desc: parse args, init stuff, run!
330+//-----------------------------------------------------------------------------
331+bool go( int argc, const char ** argv )
332+{
333+ t_CKBOOL vm_halt = TRUE;
334+ t_CKUINT srate = SAMPLE_RATE_DEFAULT;
335+ t_CKBOOL force_srate = FALSE; // added 1.3.1.2
336+ t_CKUINT buffer_size = BUFFER_SIZE_DEFAULT;
337+ t_CKUINT num_buffers = NUM_BUFFERS_DEFAULT;
338+ t_CKUINT dac = 0;
339+ t_CKUINT adc = 0;
340+ std::string dac_name = ""; // added 1.3.0.0
341+ std::string adc_name = ""; // added 1.3.0.0
342+ t_CKUINT dac_chans = 2;
343+ t_CKUINT adc_chans = 2;
344+ t_CKBOOL dump = FALSE;
345+ t_CKBOOL probe = FALSE;
346+ t_CKBOOL set_priority = FALSE;
347+ t_CKBOOL auto_depend = FALSE;
348+ t_CKBOOL block = FALSE;
349+ // t_CKBOOL enable_shell = FALSE;
350+ t_CKBOOL no_vm = FALSE;
351+ t_CKBOOL load_hid = FALSE;
352+ t_CKBOOL enable_server = TRUE;
353+ t_CKBOOL do_watchdog = TRUE;
354+ t_CKINT adaptive_size = 0;
355+ t_CKINT log_level = CK_LOG_CORE;
356+ t_CKINT deprecate_level = 1; // 1 == warn
357+ t_CKINT chugin_load = 1; // 1 == auto (variable added 1.3.0.0)
358+ // whether to make this new VM the one that receives OTF commands
359+ t_CKBOOL update_otf_vm = TRUE;
360+ string filename = "";
361+ vector<string> args;
362+
363+ // list of search pathes (added 1.3.0.0)
364+ std::list<std::string> dl_search_path;
365+ // initial chug-in path (added 1.3.0.0)
366+ std::string initial_chugin_path;
367+ // if set as environment variable (added 1.3.0.0)
368+ if( getenv( g_chugin_path_envvar ) )
369+ {
370+ // get it from the env var
371+ initial_chugin_path = getenv( g_chugin_path_envvar );
372+ }
373+ else
374+ {
375+ // default it
376+ initial_chugin_path = g_default_chugin_path;
377+ }
378+ // parse the colon list into STL list (added 1.3.0.0)
379+ parse_path_list( initial_chugin_path, dl_search_path );
380+ // list of individually named chug-ins (added 1.3.0.0)
381+ std::list<std::string> named_dls;
382+
383+#if defined(__DISABLE_WATCHDOG__)
384+ do_watchdog = FALSE;
385+#elif defined(__MACOSX_CORE__)
386+ do_watchdog = TRUE;
387+#elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__)
388+ do_watchdog = TRUE;
389+#else
390+ do_watchdog = FALSE;
391+#endif
392+
393+ t_CKUINT files = 0;
394+ t_CKUINT count = 1;
395+ t_CKINT i;
396+
397+ // set log level
398+ EM_setlog( log_level );
399+
400+ // add myself to the list of Chuck_Systems that might need to be cleaned up
401+ // g_systems.push_back( this );
402+
403+
404+ //------------------------- COMMAND LINE ARGUMENTS -----------------------------
405+
406+ // parse command line args
407+ for( i = 1; i < argc; i++ )
408+ {
409+ if( argv[i][0] == '-' || argv[i][0] == '+' ||
410+ argv[i][0] == '=' || argv[i][0] == '^' || argv[i][0] == '@' )
411+ {
412+ if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d")
413+ || !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d") )
414+ continue;
415+ else if( get_count( argv[i], &count ) )
416+ continue;
417+ else if( !strcmp(argv[i], "--audio") || !strcmp(argv[i], "-a") )
418+ g_enable_realtime_audio = TRUE;
419+ else if( !strcmp(argv[i], "--silent") || !strcmp(argv[i], "-s") )
420+ g_enable_realtime_audio = FALSE;
421+ else if( !strcmp(argv[i], "--halt") || !strcmp(argv[i], "-t") )
422+ vm_halt = TRUE;
423+ else if( !strcmp(argv[i], "--loop") || !strcmp(argv[i], "-l") )
424+ { vm_halt = FALSE; enable_server = TRUE; }
425+ else if( !strcmp(argv[i], "--server") )
426+ enable_server = TRUE;
427+ else if( !strcmp(argv[i], "--standalone") )
428+ enable_server = FALSE;
429+ else if( !strcmp(argv[i], "--callback") )
430+ block = FALSE;
431+ else if( !strcmp( argv[i], "--external-callback" ) )
432+ {
433+ // caller will call the Chuck_System->run itself
434+ m_initOnly = TRUE;
435+ // --external-callback implies --loop: wait for incoming shreds
436+ // (don't enable server, which waits on TCP8888)
437+ vm_halt = FALSE;
438+ enable_server = FALSE;
439+ // --external-callback implies --silent: don't engage the main thread hook
440+ g_enable_realtime_audio = FALSE;
441+ }
442+ // blocking removed, ge: 1.3.5.3
443+ // else if( !strcmp(argv[i], "--blocking") )
444+ // block = TRUE;
445+ else if( !strcmp(argv[i], "--hid") )
446+ load_hid = TRUE;
447+ else if( !strcmp(argv[i], "--shell") || !strcmp( argv[i], "-e" ) )
448+ { g_enable_shell = TRUE; vm_halt = FALSE; }
449+ else if( !strcmp(argv[i], "--empty") )
450+ no_vm = TRUE;
451+ else if( !strncmp(argv[i], "--srate:", 8) ) // (added 1.3.0.0)
452+ { srate = atoi( argv[i]+8 ) > 0 ? atoi( argv[i]+8 ) : srate; force_srate = TRUE; }
453+ else if( !strncmp(argv[i], "--srate", 7) )
454+ { srate = atoi( argv[i]+7 ) > 0 ? atoi( argv[i]+7 ) : srate; force_srate = TRUE; }
455+ else if( !strncmp(argv[i], "-r", 2) )
456+ { srate = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : srate; force_srate = TRUE; }
457+ else if( !strncmp(argv[i], "--bufsize:", 10) ) // (added 1.3.0.0)
458+ buffer_size = atoi( argv[i]+10 ) > 0 ? atoi( argv[i]+10 ) : buffer_size;
459+ else if( !strncmp(argv[i], "--bufsize", 9) )
460+ buffer_size = atoi( argv[i]+9 ) > 0 ? atoi( argv[i]+9 ) : buffer_size;
461+ else if( !strncmp(argv[i], "-b", 2) )
462+ buffer_size = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : buffer_size;
463+ else if( !strncmp(argv[i], "--bufnum:", 9) ) // (added 1.3.0.0)
464+ num_buffers = atoi( argv[i]+9 ) > 0 ? atoi( argv[i]+9 ) : num_buffers;
465+ else if( !strncmp(argv[i], "--bufnum", 8) )
466+ num_buffers = atoi( argv[i]+8 ) > 0 ? atoi( argv[i]+8 ) : num_buffers;
467+ else if( !strncmp(argv[i], "-n", 2) )
468+ num_buffers = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : num_buffers;
469+ else if( !strncmp(argv[i], "--dac:", 6) ) // (added 1.3.0.0)
470+ {
471+ // advance pointer to beginning of argument
472+ const char * str = argv[i]+6;
473+ char * endptr = NULL;
474+ long dev = strtol(str, &endptr, 10);
475+
476+ // check if arg was a number (added 1.3.0.0)
477+ if( endptr != NULL && *endptr == '\0' )
478+ {
479+ // successful conversion to # -- clear adc_name
480+ dac = dev;
481+ dac_name = "";
482+ }
483+ // check if arg was not a number and not empty (added 1.3.0.0)
484+ else if( *str != '\0' )
485+ {
486+ // incomplete conversion to #; see if its a possible device name
487+ dac_name = std::string(str);
488+ }
489+ else
490+ {
491+ // error
492+ CK_FPRINTF_STDERR( "[chuck]: invalid arguments for '--dac:'\n" );
493+ CK_FPRINTF_STDERR( "[chuck]: (see 'chuck --help' for more info)\n" );
494+ exit( 1 );
495+ }
496+ }
497+ else if( !strncmp(argv[i], "--dac", 5) )
498+ dac = atoi( argv[i]+6 ) > 0 ? atoi( argv[i]+6 ) : 0;
499+ else if( !strncmp(argv[i], "--adc:", 6) ) // (added 1.3.0.0)
500+ {
501+ // advance pointer to beginning of argument
502+ const char * str = argv[i]+6;
503+ char * endptr = NULL;
504+ long dev = strtol(str, &endptr, 10);
505+
506+ // check if arg was a number (added 1.3.0.0)
507+ if( endptr != NULL && *endptr == '\0' )
508+ {
509+ // successful conversion to # -- clear adc_name
510+ adc = dev;
511+ adc_name = "";
512+ }
513+ // check if arg was number a number and not empty (added 1.3.0.0)
514+ else if( *str != '\0' )
515+ {
516+ // incomplete conversion to #; see if its a possible device name
517+ adc_name = std::string(str);
518+ }
519+ else
520+ {
521+ // error
522+ CK_FPRINTF_STDERR( "[chuck]: invalid arguments for '--adc:'\n" );
523+ CK_FPRINTF_STDERR( "[chuck]: (see 'chuck --help' for more info)\n" );
524+ exit( 1 );
525+ }
526+ }
527+ else if( !strncmp(argv[i], "--adc", 5) )
528+ adc = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 0;
529+ else if( !strncmp(argv[i], "--channels:", 11) ) // (added 1.3.0.0)
530+ dac_chans = adc_chans = atoi( argv[i]+11 ) > 0 ? atoi( argv[i]+11 ) : 2;
531+ else if( !strncmp(argv[i], "--channels", 10) )
532+ dac_chans = adc_chans = atoi( argv[i]+10 ) > 0 ? atoi( argv[i]+10 ) : 2;
533+ else if( !strncmp(argv[i], "-c", 2) )
534+ dac_chans = adc_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2;
535+ else if( !strncmp(argv[i], "--out:", 6) ) // (added 1.3.0.0)
536+ dac_chans = atoi( argv[i]+6 ) > 0 ? atoi( argv[i]+6 ) : 2;
537+ else if( !strncmp(argv[i], "--out", 5) )
538+ dac_chans = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 2;
539+ else if( !strncmp(argv[i], "-o", 2) )
540+ dac_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2;
541+ else if( !strncmp(argv[i], "--in:", 5) ) // (added 1.3.0.0)
542+ adc_chans = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 2;
543+ else if( !strncmp(argv[i], "--in", 4) )
544+ adc_chans = atoi( argv[i]+4 ) > 0 ? atoi( argv[i]+4 ) : 2;
545+ else if( !strncmp(argv[i], "-i", 2) )
546+ adc_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2;
547+ else if( !strncmp(argv[i], "--level:", 8) ) // (added 1.3.0.0)
548+ { g_priority = atoi( argv[i]+8 ); set_priority = TRUE; }
549+ else if( !strncmp(argv[i], "--level", 7) )
550+ { g_priority = atoi( argv[i]+7 ); set_priority = TRUE; }
551+ else if( !strncmp(argv[i], "--watchdog", 10) )
552+ { g_watchdog_timeout = atof( argv[i]+10 );
553+ if( g_watchdog_timeout <= 0 ) g_watchdog_timeout = 0.5;
554+ do_watchdog = TRUE; }
555+ else if( !strncmp(argv[i], "--nowatchdog", 12) )
556+ do_watchdog = FALSE;
557+ else if( !strncmp(argv[i], "--remote:", 9) ) // (added 1.3.0.0)
558+ strcpy( g_host, argv[i]+9 );
559+ else if( !strncmp(argv[i], "--remote", 8) )
560+ strcpy( g_host, argv[i]+8 );
561+ else if( !strncmp(argv[i], "@", 1) )
562+ strcpy( g_host, argv[i]+1 );
563+ else if( !strncmp(argv[i], "--port:", 7) ) // (added 1.3.0.0)
564+ g_port = atoi( argv[i]+7 );
565+ else if( !strncmp(argv[i], "--port", 6) )
566+ g_port = atoi( argv[i]+6 );
567+ else if( !strncmp(argv[i], "-p", 2) )
568+ g_port = atoi( argv[i]+2 );
569+ else if( !strncmp(argv[i], "--auto", 6) )
570+ auto_depend = TRUE;
571+ else if( !strncmp(argv[i], "-u", 2) )
572+ auto_depend = TRUE;
573+ else if( !strncmp(argv[i], "--log:", 6) ) // (added 1.3.0.0)
574+ log_level = argv[i][6] ? atoi( argv[i]+6 ) : CK_LOG_INFO;
575+ else if( !strncmp(argv[i], "--log", 5) )
576+ log_level = argv[i][5] ? atoi( argv[i]+5 ) : CK_LOG_INFO;
577+ else if( !strncmp(argv[i], "--verbose:", 10) ) // (added 1.3.0.0)
578+ log_level = argv[i][10] ? atoi( argv[i]+10 ) : CK_LOG_INFO;
579+ else if( !strncmp(argv[i], "--verbose", 9) )
580+ log_level = argv[i][9] ? atoi( argv[i]+9 ) : CK_LOG_INFO;
581+ else if( !strncmp(argv[i], "-v", 2) )
582+ log_level = argv[i][2] ? atoi( argv[i]+2 ) : CK_LOG_INFO;
583+ else if( !strncmp(argv[i], "--adaptive:", 11) ) // (added 1.3.0.0)
584+ adaptive_size = argv[i][11] ? atoi( argv[i]+11 ) : -1;
585+ else if( !strncmp(argv[i], "--adaptive", 10) )
586+ adaptive_size = argv[i][10] ? atoi( argv[i]+10 ) : -1;
587+ else if( !strncmp(argv[i], "--deprecate", 11) )
588+ {
589+ // get the rest
590+ string arg = argv[i]+11;
591+ if( arg == ":stop" ) deprecate_level = 0;
592+ else if( arg == ":warn" ) deprecate_level = 1;
593+ else if( arg == ":ignore" ) deprecate_level = 2;
594+ else
595+ {
596+ // error
597+ CK_FPRINTF_STDERR( "[chuck]: invalid arguments for '--deprecate'...\n" );
598+ CK_FPRINTF_STDERR( "[chuck]: ... (looking for :stop, :warn, or :ignore)\n" );
599+ exit( 1 );
600+ }
601+ }
602+ // (added 1.3.0.0)
603+ else if( !strncmp(argv[i], "--chugin-load:", sizeof("--chugin-load:")-1) )
604+ {
605+ // get the rest
606+ string arg = argv[i]+sizeof("--chugin-load:")-1;
607+ if( arg == "off" ) chugin_load = 0;
608+ else if( arg == "auto" ) chugin_load = 1;
609+ else
610+ {
611+ // error
612+ CK_FPRINTF_STDERR( "[chuck]: invalid arguments for '--chugin-load'...\n" );
613+ CK_FPRINTF_STDERR( "[chuck]: ... (looking for :auto or :off)\n" );
614+ exit( 1 );
615+ }
616+ }
617+ // (added 1.3.0.0)
618+ else if( !strncmp(argv[i], "--chugin-path:", sizeof("--chugin-path:")-1) )
619+ {
620+ // get the rest
621+ dl_search_path.push_back( argv[i]+sizeof("--chugin-path:")-1 );
622+ }
623+ // (added 1.3.0.0)
624+ else if( !strncmp(argv[i], "-G", sizeof("-G")-1) )
625+ {
626+ // get the rest
627+ dl_search_path.push_back( argv[i]+sizeof("-G")-1 );
628+ }
629+ // (added 1.3.0.0)
630+ else if( !strncmp(argv[i], "--chugin:", sizeof("--chugin:")-1) )
631+ {
632+ named_dls.push_back(argv[i]+sizeof("--chugin:")-1);
633+ }
634+ // (added 1.3.0.0)
635+ else if( !strncmp(argv[i], "-g", sizeof("-g")-1) )
636+ {
637+ named_dls.push_back(argv[i]+sizeof("-g")-1);
638+ }
639+ else if( !strncmp( argv[i], "--data-dir:", sizeof("--data-dir:")-1 ) )
640+ {
641+ // get the rest, store for later
642+ m_dataDir = std::string( argv[i]+sizeof("--data-dir:")-1 );
643+ // also look for chugins here
644+ dl_search_path.push_back( m_dataDir );
645+ }
646+ else if( !strcmp( argv[i], "--no-otf" ) )
647+ {
648+ // don't use this new vm for otf commands (use the previous one)
649+ update_otf_vm = FALSE;
650+ }
651+ else if( !strcmp( argv[i], "--probe" ) )
652+ probe = TRUE;
653+ else if( !strcmp( argv[i], "--poop" ) )
654+ uh();
655+ else if( !strcmp( argv[i], "--caution-to-the-wind" ) )
656+ g_enable_system_cmd = TRUE;
657+ else if( !strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")
658+ || !strcmp(argv[i], "--about") )
659+ {
660+ usage();
661+ exit( 2 );
662+ }
663+ else if( !strcmp( argv[i], "--version" ) )
664+ {
665+ version();
666+ exit( 2 );
667+ }
668+ else
669+ {
670+ // boost log level
671+ g_otf_log = CK_LOG_CORE;
672+ // flag
673+ int is_otf = FALSE;
674+ // log level
675+ EM_setlog( log_level );
676+
677+ // do it
678+ if( otf_send_cmd( argc, argv, i, g_host, g_port, &is_otf ) )
679+ exit( 0 );
680+
681+ // is otf
682+ if( is_otf ) exit( 1 );
683+
684+ // done
685+ CK_FPRINTF_STDERR( "[chuck]: invalid flag '%s'\n", argv[i] );
686+ usage();
687+ exit( 1 );
688+ }
689+ }
690+ else // doesn't look like an argument
691+ {
692+ // increase number of files
693+ files++;
694+ }
695+ }
696+
697+ // log level
698+ EM_setlog( log_level );
699+
700+ // probe
701+ if( probe )
702+ {
703+ Digitalio::probe();
704+
705+#ifndef __DISABLE_MIDI__
706+ EM_error2b( 0, "" );
707+ probeMidiIn();
708+ EM_error2b( 0, "" );
709+ probeMidiOut();
710+ EM_error2b( 0, "" );
711+#endif // __DISABLE_MIDI__
712+
713+ // HidInManager::probeHidIn();
714+
715+ // exit
716+ exit( 0 );
717+ }
718+
719+ // check buffer size
720+ buffer_size = ensurepow2( buffer_size );
721+ // check mode and blocking
722+ if( !g_enable_realtime_audio && !block ) block = TRUE;
723+ // audio, boost
724+ if( !set_priority && !block ) g_priority = g_priority_low;
725+ if( !set_priority && !g_enable_realtime_audio ) g_priority = 0x7fffffff;
726+ // set priority
727+ Chuck_VM::our_priority = g_priority;
728+ // set watchdog
729+ g_do_watchdog = do_watchdog;
730+ // set adaptive size
731+ if( adaptive_size < 0 ) adaptive_size = buffer_size;
732+
733+ // check
734+ if( clientMode )
735+ {
736+ // silent mode always in client mode
737+ g_enable_realtime_audio = FALSE;
738+ // no halt
739+ vm_halt = FALSE;
740+ }
741+
742+ if ( !files && vm_halt && !g_enable_shell && !clientMode )
743+ {
744+ CK_FPRINTF_STDERR( "[chuck]: no input files... (try --help)\n" );
745+ exit( 1 );
746+ }
747+
748+ // shell initialization without vm
749+ if( g_enable_shell && no_vm )
750+ {
751+ // instantiate
752+ g_shell = new Chuck_Shell;
753+ // initialize
754+ if( !init_shell( g_shell, new Chuck_Console, NULL ) )
755+ exit( 1 );
756+ // no vm is needed, just start running the shell now
757+ g_shell->run();
758+ // clean up
759+ SAFE_DELETE( g_shell );
760+ // done
761+ exit( 0 );
762+ }
763+
764+ // make sure vm
765+ if( no_vm )
766+ {
767+ CK_FPRINTF_STDERR( "[chuck]: '--empty' can only be used with shell...\n" );
768+ exit( 1 );
769+ }
770+
771+ // find dac_name if appropriate (added 1.3.0.0)
772+ if( dac_name.size() > 0 )
773+ {
774+ // check with RtAudio
775+ int dev = Digitalio::device_named( dac_name, TRUE, FALSE );
776+ if( dev >= 0 )
777+ {
778+ dac = dev;
779+ }
780+ else
781+ {
782+ CK_FPRINTF_STDERR( "[chuck]: unable to find dac '%s'...\n", dac_name.c_str() );
783+ CK_FPRINTF_STDERR( "[chuck]: | (try --probe to enumerate audio device info)\n" );
784+ exit( 1 );
785+ }
786+ }
787+
788+ // find adc_name if appropriate (added 1.3.0.0)
789+ if( adc_name.size() > 0 )
790+ {
791+ // check with RtAudio
792+ int dev = Digitalio::device_named( adc_name, FALSE, TRUE );
793+ if( dev >= 0 )
794+ {
795+ adc = dev;
796+ }
797+ else
798+ {
799+ CK_FPRINTF_STDERR( "[chuck]: unable to find adc '%s'...\n", adc_name.c_str() );
800+ CK_FPRINTF_STDERR( "[chuck]: | (try --probe to enumerate audio device info)\n" );
801+ exit( 1 );
802+ }
803+ }
804+
805+ //------------------------- VIRTUAL MACHINE SETUP -----------------------------
806+ // instantiate ChucK
807+ the_chuck = new ChucK();
808+
809+
810+
811+ //------------------------- VIRTUAL MACHINE SETUP -----------------------------
812+
813+ // allocate the vm - needs the type system
814+ vm = m_carrier.vm = m_vmRef = new Chuck_VM;
815+ m_carrier.vm->setCarrier( &m_carrier );
816+
817+ // ge: refactor 2015: initialize VM
818+ if( !vm->initialize( srate, dac_chans, adc_chans, adaptive_size, vm_halt ) )
819+ {
820+ CK_FPRINTF_STDERR( "[chuck]: %s\n", vm->last_error() );
821+ exit( 1 );
822+ }
823+
824+ if( update_otf_vm )
825+ {
826+ set_otf_vm( vm );
827+ }
828+
829+
830+ //--------------------------- AUDIO I/O SETUP ---------------------------------
831+ // initialize audio system
832+ t_CKBOOL retval = ChuckAudio::initialize( numInChannels, numOutChannels,
833+ srate, bufferSize, numBuffers, cb, NULL, FALSE );
834+ // check
835+ if( !retval )
836+ {
837+ // BADDDD
838+ }
839+
840+ // ge: 1.3.5.3
841+ if( g_bbq == NULL ) {
842+ bbq = g_bbq = new BBQ;
843+ // set some parameters
844+ bbq->set_srate( srate );
845+ bbq->set_bufsize( buffer_size );
846+ bbq->set_numbufs( num_buffers );
847+ bbq->set_inouts( adc, dac );
848+ bbq->set_chans( adc_chans, dac_chans );
849+
850+ // log
851+ EM_log( CK_LOG_SYSTEM, "initializing audio I/O..." );
852+ // push
853+ EM_pushlog();
854+ // log
855+ EM_log( CK_LOG_SYSTEM, "probing '%s' audio subsystem...", g_enable_realtime_audio ? "real-time" : "fake-time" );
856+
857+ // probe / init (this shouldn't start audio yet...
858+ // moved here 1.3.1.2; to main ge: 1.3.5.3)
859+ if( !bbq->initialize( dac_chans, adc_chans, srate, 16, buffer_size, num_buffers,
860+ dac, adc, block, vm, g_enable_realtime_audio, NULL, NULL, force_srate ) )
861+ {
862+ EM_log( CK_LOG_SYSTEM,
863+ "cannot initialize audio device (use --silent/-s for non-realtime)" );
864+ // pop
865+ EM_poplog();
866+ // done
867+ exit( 1 );
868+ }
869+
870+ // log
871+ EM_log( CK_LOG_SYSTEM, "real-time audio: %s", g_enable_realtime_audio ? "YES" : "NO" );
872+ EM_log( CK_LOG_SYSTEM, "mode: %s", block ? "BLOCKING" : "CALLBACK" );
873+ EM_log( CK_LOG_SYSTEM, "sample rate: %ld", srate );
874+ EM_log( CK_LOG_SYSTEM, "buffer size: %ld", buffer_size );
875+ if( g_enable_realtime_audio )
876+ {
877+ EM_log( CK_LOG_SYSTEM, "num buffers: %ld", num_buffers );
878+ EM_log( CK_LOG_SYSTEM, "adc: %ld dac: %d", adc, dac );
879+ EM_log( CK_LOG_SYSTEM, "adaptive block processing: %ld", adaptive_size > 1 ? adaptive_size : 0 );
880+ }
881+ EM_log( CK_LOG_SYSTEM, "channels in: %ld out: %ld", adc_chans, dac_chans );
882+
883+ // pop
884+ EM_poplog();
885+ } else {
886+ bbq = g_bbq;
887+ }
888+
889+ //------------------------- CHUCK COMPILER SETUP -----------------------------
890+
891+ // if chugin load is off, then clear the lists (added 1.3.0.0 -- TODO: refactor)
892+ if( chugin_load == 0 )
893+ {
894+ // turn off chugin load
895+ dl_search_path.clear();
896+ named_dls.clear();
897+ }
898+
899+ // allocate the compiler
900+ compiler = m_carrier.compiler = m_compilerRef = new Chuck_Compiler;
901+ m_carrier.compiler->setCarrier( &m_carrier );
902+
903+ // initialize the compiler (search_apth and named_dls added 1.3.0.0 -- TODO: refactor)
904+ if( !compiler->initialize( dl_search_path, named_dls ) )
905+ {
906+ CK_FPRINTF_STDERR( "[chuck]: error initializing compiler...\n" );
907+ exit( 1 );
908+ }
909+ // enable dump
910+ compiler->emitter->dump = dump;
911+ // set auto depend
912+ compiler->set_auto_depend( auto_depend );
913+
914+ if( update_otf_vm )
915+ {
916+ // also update otf compiler
917+ set_otf_compiler( compiler );
918+ }
919+
920+ // vm synthesis subsystem - needs the type system
921+ if( !vm->initialize_synthesis( ) )
922+ {
923+ CK_FPRINTF_STDERR( "[chuck]: %s\n", vm->last_error() );
924+ exit( 1 );
925+ }
926+
927+#ifndef __ALTER_HID__
928+ // pre-load hid
929+ if( load_hid ) HidInManager::init();
930+#endif // __ALTER_HID__
931+
932+ // catch SIGINT
933+ signal( SIGINT, signal_int );
934+#ifndef __PLATFORM_WIN32__
935+ // catch SIGPIPE
936+ signal( SIGPIPE, signal_pipe );
937+#endif
938+
939+ // shell initialization
940+ if( g_enable_shell )
941+ {
942+ // instantiate
943+ g_shell = new Chuck_Shell;
944+ // initialize
945+ if( !init_shell( g_shell, new Chuck_Console, vm ) )
946+ exit( 1 );
947+ }
948+
949+ // set deprecate
950+ compiler->env()->deprecate_level = deprecate_level;
951+
952+ // reset count
953+ count = 1;
954+
955+ // figure out current working directory (added 1.3.0.0)
956+ std::string cwd;
957+ {
958+ char cstr_cwd[MAXPATHLEN];
959+ if( getcwd(cstr_cwd, MAXPATHLEN) == NULL )
960+ {
961+ // uh...
962+ EM_log( CK_LOG_SEVERE, "error: unable to determine current working directory!" );
963+ }
964+ else
965+ {
966+ cwd = std::string(cstr_cwd);
967+ cwd = normalize_directory_separator(cwd) + "/";
968+ }
969+ }
970+
971+ // whether or not chug should be enabled (added 1.3.0.0)
972+ if( chugin_load )
973+ {
974+ // log
975+ EM_log( CK_LOG_SEVERE, "pre-loading ChucK libs..." );
976+ EM_pushlog();
977+
978+ // iterate over list of ck files that the compiler found
979+ for( std::list<std::string>::iterator j = compiler->m_cklibs_to_preload.begin();
980+ j != compiler->m_cklibs_to_preload.end(); j++)
981+ {
982+ // the filename
983+ std::string filename = *j;
984+
985+ // log
986+ EM_log( CK_LOG_SEVERE, "preloading '%s'...", filename.c_str() );
987+ // push indent
988+ EM_pushlog();
989+
990+ // SPENCERTODO: what to do for full path
991+ std::string full_path = filename;
992+
993+ // parse, type-check, and emit
994+ if( compiler->go( filename, NULL, NULL, full_path ) )
995+ {
996+ // TODO: how to compilation handle?
997+ //return 1;
998+
999+ // get the code
1000+ code = compiler->output();
1001+ // name it - TODO?
1002+ // code->name += string(argv[i]);
1003+
1004+ // spork it
1005+ shred = vm->spork( code, NULL, TRUE );
1006+ }
1007+
1008+ // pop indent
1009+ EM_poplog();
1010+ }
1011+
1012+ // clear the list of chuck files to preload
1013+ compiler->m_cklibs_to_preload.clear();
1014+
1015+ // pop log
1016+ EM_poplog();
1017+ }
1018+
1019+ compiler->env()->load_user_namespace();
1020+
1021+ // log
1022+ EM_log( CK_LOG_SEVERE, "starting compilation..." );
1023+ // push indent
1024+ EM_pushlog();
1025+
1026+
1027+ //------------------------- SOURCE COMPILATION --------------------------------
1028+
1029+ // loop through and process each file
1030+ for( i = 1; i < argc; i++ )
1031+ {
1032+ // make sure
1033+ if( argv[i][0] == '-' || argv[i][0] == '+' )
1034+ {
1035+ if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d" ) )
1036+ compiler->emitter->dump = TRUE;
1037+ else if( !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d" ) )
1038+ compiler->emitter->dump = FALSE;
1039+ else
1040+ get_count( argv[i], &count );
1041+
1042+ continue;
1043+ }
1044+
1045+ // compile it!
1046+ compileFile( argv[i], "", count );
1047+
1048+ // reset count
1049+ count = 1;
1050+ }
1051+
1052+ // pop indent
1053+ EM_poplog();
1054+
1055+ // reset the parser
1056+ reset_parse();
1057+
1058+ // boost priority
1059+ if( Chuck_VM::our_priority != 0x7fffffff )
1060+ {
1061+ // try
1062+ if( !Chuck_VM::set_priority( Chuck_VM::our_priority, vm ) )
1063+ {
1064+ // error
1065+ CK_FPRINTF_STDERR( "[chuck]: %s\n", vm->last_error() );
1066+ exit( 1 );
1067+ }
1068+ }
1069+
1070+
1071+ //----------------------- ON-THE-FLY SERVER SETUP -----------------------------
1072+
1073+ // server
1074+ if( enable_server )
1075+ {
1076+#ifndef __DISABLE_OTF_SERVER__
1077+ // log
1078+ EM_log( CK_LOG_SYSTEM, "starting listener on port: %d...", g_port );
1079+
1080+ // start tcp server
1081+ g_sock = ck_tcp_create( 1 );
1082+ if( !g_sock || !ck_bind( g_sock, g_port ) || !ck_listen( g_sock, 10 ) )
1083+ {
1084+ CK_FPRINTF_STDERR( "[chuck]: cannot bind to tcp port %li...\n", g_port );
1085+ ck_close( g_sock );
1086+ g_sock = NULL;
1087+ }
1088+ else
1089+ {
1090+#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
1091+ pthread_create( &g_tid_otf, NULL, otf_cb, NULL );
1092+#else
1093+ g_tid_otf = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)otf_cb, NULL, 0, 0 );
1094+#endif
1095+ }
1096+#endif // __DISABLE_OTF_SERVER__
1097+ }
1098+ else
1099+ {
1100+ // log
1101+ EM_log( CK_LOG_SYSTEM, "OTF server/listener: OFF" );
1102+ }
1103+
1104+ // start shell on separate thread
1105+ if( g_enable_shell )
1106+ {
1107+#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
1108+ pthread_create( &g_tid_shell, NULL, shell_cb, g_shell );
1109+#else
1110+ g_tid_shell = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)shell_cb, g_shell, 0, 0 );
1111+#endif
1112+ }
1113+
1114+
1115+ //-------------------------- MAIN CHUCK LOOP!!! -----------------------------
1116+
1117+ // log
1118+ EM_log( CK_LOG_SYSTEM, "running main loop..." );
1119+ // push indent
1120+ EM_pushlog();
1121+
1122+ // set run state
1123+ vm->start();
1124+
1125+ EM_log( CK_LOG_SEVERE, "initializing audio buffers..." );
1126+ if( !bbq->digi_out()->initialize( ) )
1127+ {
1128+ EM_log( CK_LOG_SYSTEM,
1129+ "cannot open audio output (use --silent/-s)" );
1130+ exit(1);
1131+ }
1132+
1133+ // initialize input
1134+ bbq->digi_in()->initialize( );
1135+
1136+ // log
1137+ EM_log( CK_LOG_SEVERE, "virtual machine running..." );
1138+ // pop indent
1139+ EM_poplog();
1140+
1141+ // NOTE: non-blocking callback only, ge: 1.3.5.3
1142+
1143+ // compute shreds before first sample
1144+ if( !vm->compute() )
1145+ {
1146+ // done, 1.3.5.3
1147+ vm->stop();
1148+ // log
1149+ EM_log( CK_LOG_SYSTEM, "virtual machine stopped..." );
1150+ }
1151+
1152+ // check client mode
1153+ if( clientMode )
1154+ {
1155+ // done!
1156+ return TRUE;
1157+ }
1158+
1159+ // start audio
1160+ if( !audio_started )
1161+ {
1162+ // audio
1163+ if( !audio_started && g_enable_realtime_audio )
1164+ {
1165+ EM_log( CK_LOG_SEVERE, "starting real-time audio..." );
1166+ bbq->digi_out()->start();
1167+ bbq->digi_in()->start();
1168+ }
1169+
1170+ // set the flag to true to avoid entering this function
1171+ audio_started = TRUE;
1172+ }
1173+
1174+
1175+ // Don't run audio callback and shut down if we only wanted to init here
1176+ if( m_initOnly ) {
1177+ return TRUE;
1178+ }
1179+
1180+
1181+ // silent mode buffers
1182+ SAMPLE * input = new SAMPLE[buffer_size*adc_chans];
1183+ SAMPLE * output = new SAMPLE[buffer_size*dac_chans];
1184+ // zero out
1185+ memset( input, 0, sizeof(SAMPLE)*buffer_size*adc_chans );
1186+ memset( output, 0, sizeof(SAMPLE)*buffer_size*dac_chans );
1187+
1188+ // wait
1189+ while( vm->running() )
1190+ {
1191+ // real-time audio
1192+ if( g_enable_realtime_audio )
1193+ {
1194+ if( g_main_thread_hook && g_main_thread_quit )
1195+ g_main_thread_hook( g_main_thread_bindle );
1196+ else
1197+ usleep( 1000 );
1198+ }
1199+ else // silent mode
1200+ {
1201+ // keep running as fast as possible
1202+ this->run( input, output, buffer_size );
1203+ }
1204+ }
1205+
1206+ // shutdown
1207+ clientShutdown();
1208+
1209+ return TRUE;
1210+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t