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
23-----------------------------------------------------------------------------*/23-----------------------------------------------------------------------------*/
24 24
25//-----------------------------------------------------------------------------25//-----------------------------------------------------------------------------
26// name: digiio_rtaudio.cpp26// name: chuck_audio.cpp
27// desc: digitalio over RtAudio (from Gary Scavone)27// desc: chuck host digital audio I/O, using RtAudio
28//28//
29// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)29// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30// Spencer Salazar (spencer@ccrma.stanford.edu)30// Spencer Salazar (spencer@ccrma.stanford.edu)
31// RtAudio by: Gary Scavone31// RtAudio by: Gary Scavone
32// date: Spring 200432//
33// date: Spring 2004 -- initial versions
34// Fall 2017 -- REFACTOR-2017: clean up to be more modular
33//-----------------------------------------------------------------------------35//-----------------------------------------------------------------------------
34#include "digiio_rtaudio.h"36#include "chuck_audio.h"
35#include "chuck_vm.h"
36#include "chuck_errmsg.h"37#include "chuck_errmsg.h"
37#include "chuck_globals.h"38#include "chuck_globals.h"
38#include <limits.h>39#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__
46#include "rtmidi.h"40#include "rtmidi.h"
47#endif // __DISABLE_MIDI__41
48// #include <signal.h>
49#if (defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)) && !defined(__WINDOWS_PTHREAD__)42#if (defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)) && !defined(__WINDOWS_PTHREAD__)
50#include <windows.h>43 #include <windows.h>
51#include <sys/timeb.h>44 #include <sys/timeb.h>
52#else45#else
53#include <unistd.h>46 #include <unistd.h>
54#include <sys/time.h>47 #include <sys/time.h>
55#endif48#endif
56 49
57// extern "C" void signal_int( int );50
58
59// static
60BOOL__ Digitalio::m_init = FALSE;
61DWORD__ Digitalio::m_start = 0;
62DWORD__ Digitalio::m_tick_count = 0;
63DWORD__ Digitalio::m_num_channels_out = NUM_CHANNELS_DEFAULT;
64DWORD__ Digitalio::m_num_channels_in = NUM_CHANNELS_DEFAULT;
65DWORD__ Digitalio::m_sampling_rate = SAMPLING_RATE_DEFAULT;
66DWORD__ Digitalio::m_bps = BITS_PER_SAMPLE_DEFAULT;
67DWORD__ Digitalio::m_buffer_size = BUFFER_SIZE_DEFAULT;
68DWORD__ Digitalio::m_num_buffers = NUM_BUFFERS_DEFAULT;
69RtAudio * Digitalio::m_rtaudio = NULL;
70SAMPLE * Digitalio::m_buffer_out = NULL;
71SAMPLE * Digitalio::m_buffer_in = NULL;
72SAMPLE ** Digitalio::m_write_ptr = NULL;
73SAMPLE ** Digitalio::m_read_ptr = NULL;
74SAMPLE * Digitalio::m_extern_in = NULL;
75SAMPLE * Digitalio::m_extern_out = NULL;
76BOOL__ Digitalio::m_out_ready = FALSE;
77BOOL__ Digitalio::m_in_ready = FALSE;
78BOOL__ Digitalio::m_use_cb = USE_CB_DEFAULT;
79DWORD__ Digitalio::m_go = 0;
80DWORD__ Digitalio::m_dac_n = 0;
81DWORD__ Digitalio::m_adc_n = 0;
82DWORD__ Digitalio::m_end = 0;
83DWORD__ Digitalio::m_block = TRUE;
84DWORD__ Digitalio::m_xrun = 0;
85 51
86 52
87// sample53// sample
@@ -94,7 +60,29 @@ DWORD__ Digitalio::m_xrun = 0; · 6 unmodified lines
94 60
95 61
96 62
97#ifndef __DISABLE_RTAUDIO__63// static initialization
64t_CKBOOL ChuckAudio::m_init = FALSE;
65t_CKBOOL ChuckAudio::m_start = FALSE;
66t_CKBOOL ChuckAudio::m_go = FALSE;
67t_CKBOOL ChuckAudio::m_silent = FALSE;
68t_CKUINT ChuckAudio::m_num_channels_out = NUM_CHANNELS_DEFAULT;
69t_CKUINT ChuckAudio::m_num_channels_in = NUM_CHANNELS_DEFAULT;
70t_CKUINT ChuckAudio::m_sample_rate = SAMPLE_RATE_DEFAULT;
71t_CKUINT ChuckAudio::m_buffer_size = BUFFER_SIZE_DEFAULT;
72t_CKUINT ChuckAudio::m_num_buffers = NUM_BUFFERS_DEFAULT;
73SAMPLE * ChuckAudio::m_buffer_out = NULL;
74SAMPLE * ChuckAudio::m_buffer_in = NULL;
75SAMPLE * ChuckAudio::m_extern_in = NULL;
76SAMPLE * ChuckAudio::m_extern_out = NULL;
77t_CKUINT ChuckAudio::m_dac_n = 0;
78t_CKUINT ChuckAudio::m_adc_n = 0;
79RtAudio * ChuckAudio::m_rtaudio = NULL;
80f_audio_cb ChuckAudio::m_audio_cb = NULL;
81void * ChuckAudio::m_cb_user_data = NULL;
82
83
84
85
98//-----------------------------------------------------------------------------86//-----------------------------------------------------------------------------
99// name: print()87// name: print()
100// desc: ...88// desc: ...
@@ -134,7 +122,6 @@ void print( const RtAudio::DeviceInfo & info ) · 33 unmodified lines
134 }122 }
135 }123 }
136}124}
137#endif // __DISABLE_RTAUDIO__
138 125
139 126
140 127
@@ -143,14 +130,15 @@ void print( const RtAudio::DeviceInfo & info ) · 2 unmodified lines
143// name: probe()130// name: probe()
144// desc: ...131// desc: ...
145//-----------------------------------------------------------------------------132//-----------------------------------------------------------------------------
146void Digitalio::probe()133void ChuckAudio::probe()
147{134{
148#ifndef __DISABLE_RTAUDIO__135 // rtaduio pointer
149 RtAudio * rta = NULL;136 RtAudio * audio = NULL;
137 // device info struct
150 RtAudio::DeviceInfo info;138 RtAudio::DeviceInfo info;
151 139
152 // allocate RtAudio140 // allocate RtAudio
153 try { rta = new RtAudio( ); }141 try { audio = new RtAudio( ); }
154 catch( RtError err )142 catch( RtError err )
155 {143 {
156 // problem finding audio devices, most likely144 // problem finding audio devices, most likely
@@ -158,17 +146,17 @@ void Digitalio::probe() · 1 unmodified line
158 return;146 return;
159 }147 }
160 148
161 // get count 149 // get count
162 int devices = rta->getDeviceCount();150 int devices = audio->getDeviceCount();
163 EM_error2b( 0, "found %d device(s) ...", devices );151 EM_error2b( 0, "found %d device(s) ...", devices );
164 // EM_error2( 0, "--------------------------" );152
165 153 // reset -- what does this do
166 EM_reset_msg();154 EM_reset_msg();
167 155
168 // loop156 // loop over devices
169 for( int i = 0; i < devices; i++ )157 for( int i = 0; i < devices; i++ )
170 {158 {
171 try { info = rta->getDeviceInfo(i); }159 try { info = audio->getDeviceInfo(i); }
172 catch( RtError & error )160 catch( RtError & error )
173 {161 {
174 error.printMessage();162 error.printMessage();
@@ -181,11 +169,12 @@ void Digitalio::probe() · 6 unmodified lines
181 // skip169 // skip
182 if( i < devices ) EM_error2( 0, "" );170 if( i < devices ) EM_error2( 0, "" );
183 171
172 // reset
184 EM_reset_msg();173 EM_reset_msg();
185 }174 }
186 175
187 delete rta;176 // done
188#endif // __DISABLE_RTAUDIO__177 SAFE_DELETE( audio );
189 178
190 return;179 return;
191}180}
@@ -195,16 +184,19 @@ void Digitalio::probe() · 3 unmodified lines
195 184
196//-----------------------------------------------------------------------------185//-----------------------------------------------------------------------------
197// name: device_named()186// 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
199//-----------------------------------------------------------------------------189//-----------------------------------------------------------------------------
200DWORD__ Digitalio::device_named( const std::string & name, t_CKBOOL needs_dac, t_CKBOOL needs_adc )190t_CKUINT ChuckAudio::device_named( const std::string & name, t_CKBOOL needs_dac,
191 t_CKBOOL needs_adc )
201{192{
202#ifndef __DISABLE_RTAUDIO__193 // rtaudio pointer
203 RtAudio * rta = NULL;194 RtAudio * audio = NULL;
195 // device info struct
204 RtAudio::DeviceInfo info;196 RtAudio::DeviceInfo info;
205 197
206 // allocate RtAudio198 // allocate RtAudio
207 try { rta = new RtAudio( ); }199 try { audio = new RtAudio(); }
208 catch( RtError err )200 catch( RtError err )
209 {201 {
210 // problem finding audio devices, most likely202 // 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
219 // loop211 // loop
220 for( int i = 0; i < devices; i++ )212 for( int i = 0; i < devices; i++ )
221 {213 {
222 try { info = rta->getDeviceInfo(i); }214 // get info
215 try { info = audio->getDeviceInfo(i); }
223 catch( RtError & error )216 catch( RtError & error )
224 {217 {
225 error.printMessage();218 error.printMessage();
226 break;219 break;
227 }220 }
228 221
222 // compare name
229 if( info.name.compare(name) == 0 )223 if( info.name.compare(name) == 0 )
230 {224 {
225 // found!
231 device_no = i+1;226 device_no = i+1;
232 break;227 break;
233 }228 }
234 }229 }
235 230
231 // not found, yet
236 if( device_no == -1 )232 if( device_no == -1 )
237 {233 {
238 // no exact match found; try partial match234 // no exact match found; try partial match
239 for( int i = 0; i < devices; i++ )235 for( int i = 0; i < devices; i++ )
240 {236 {
241 try { info = rta->getDeviceInfo(i); }237 try { info = audio->getDeviceInfo(i); }
242 catch( RtError & error )238 catch( RtError & error )
243 {239 {
244 error.printMessage();240 error.printMessage();
@@ -247,9 +243,11 @@ DWORD__ Digitalio::device_named( const std::string & name, t_CKBOOL needs_dac, t · 2 unmodified lines
247 243
248 if( info.name.find(name) != std::string::npos )244 if( info.name.find(name) != std::string::npos )
249 {245 {
246 // skip over ones with 0 channels, if needed
250 if( (needs_dac && info.outputChannels == 0) ||247 if( (needs_dac && info.outputChannels == 0) ||
251 (needs_adc && info.inputChannels == 0) )248 (needs_adc && info.inputChannels == 0) )
252 continue;249 continue;
250 // found
253 device_no = i+1;251 device_no = i+1;
254 break;252 break;
255 }253 }
@@ -257,65 +255,13 @@ DWORD__ Digitalio::device_named( const std::string & name, t_CKBOOL needs_dac, t · 1 unmodified line
257 }255 }
258 256
259 // clean up257 // clean up
260 SAFE_DELETE( rta );258 SAFE_DELETE( audio );
261 259
262 // done260 // done
263 return device_no;261 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//-----------------------------------------------------------------------------
277static 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;
298}262}
299#else
300//-----------------------------------------------------------------------------
301// name: set_priority()
302// desc: ...
303//-----------------------------------------------------------------------------
304static 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 );
311 263
312 // set the priority the thread
313 if( !SetThreadPriority( tid, priority ) )
314 return FALSE;
315 264
316 return TRUE;
317}
318#endif
319 265
320 266
321//-----------------------------------------------------------------------------267//-----------------------------------------------------------------------------
@@ -333,11 +279,11 @@ static t_CKFLOAT get_current_time( t_CKBOOL fresh = TRUE ) · 11 unmodified lines
333 if( fresh ) gettimeofday(&t,NULL);279 if( fresh ) gettimeofday(&t,NULL);
334 return t.tv_sec + (t_CKFLOAT)t.tv_usec/1000000;280 return t.tv_sec + (t_CKFLOAT)t.tv_usec/1000000;
335#endif281#endif
336
337 return 0;
338}282}
339 283
340 284
285
286
341// watch dog globals287// watch dog globals
342static CHUCK_THREAD g_tid_synthesis = 0;288static CHUCK_THREAD g_tid_synthesis = 0;
343static XThread * g_watchdog_thread = NULL;289static XThread * g_watchdog_thread = NULL;
@@ -345,9 +291,11 @@ static t_CKBOOL g_watchdog_state = FALSE; · 1 unmodified line
345static t_CKFLOAT g_watchdog_time = 0;291static t_CKFLOAT g_watchdog_time = 0;
346 292
347 293
294
295
348//-----------------------------------------------------------------------------296//-----------------------------------------------------------------------------
349// name: watch_dog()297// name: watch_dog()
350// desc: ...298// desc: this sniff out possible non-time advancing infinite loops
351//-----------------------------------------------------------------------------299//-----------------------------------------------------------------------------
352#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)300#if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
353static void * watch_dog( void * )301static void * watch_dog( void * )
@@ -355,7 +303,8 @@ static void * watch_dog( void * ) · 1 unmodified line
355static unsigned int __stdcall watch_dog( void * )303static unsigned int __stdcall watch_dog( void * )
356#endif304#endif
357{305{
358 t_CKFLOAT time;306 // time
307 t_CKFLOAT time = 0;
359 308
360 // boost priority?309 // boost priority?
361 t_CKUINT priority = Chuck_VM::our_priority;310 t_CKUINT priority = Chuck_VM::our_priority;
@@ -371,43 +320,41 @@ static unsigned int __stdcall watch_dog( void * ) · 9 unmodified lines
371 EM_poplog();320 EM_poplog();
372 321
373 // boost watchdog by same priority322 // boost watchdog by same priority
374 if( Chuck_VM::our_priority != 0x7fffffff )323 if( XThreadUtil::our_priority != 0x7fffffff )
375 Chuck_VM::set_priority( priority, NULL );324 XThreadUtil::set_priority( priority );
376 325
377 // while going326 // while going
378 while( g_do_watchdog )327 while( g_do_watchdog )
379 {328 {
380 // get329 // get
381 time = get_current_time( TRUE );330 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 );
383 332
384 // resting333 // resting
385 if( g_watchdog_state == FALSE )334 if( g_watchdog_state == FALSE )
386 {335 {
387 // check xrun336 // check time vs timeout
388 // if( Digitalio::m_xrun > 100 )
389 if( time - g_watchdog_time > g_watchdog_timeout )337 if( time - g_watchdog_time > g_watchdog_timeout )
390 {338 {
391 // log339 // log
392 EM_log( CK_LOG_SEVERE, "real-time watchdog counter-measure activating..." );340 EM_log( CK_LOG_SEVERE, "real-time watchdog counter-measure activating..." );
393 // lowering priority341 // lowering priority
394 if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff )342 if( g_tid_synthesis && XThreadUtil::our_priority != 0x7fffffff )
395 set_priority( g_tid_synthesis, g_watchdog_countermeasure_priority );343 XThreadUtil::set_priority( g_tid_synthesis, g_watchdog_countermeasure_priority );
396 // set state344 // set state
397 g_watchdog_state = TRUE;345 g_watchdog_state = TRUE;
398 }346 }
399 }347 }
400 else348 else
401 {349 {
402 // check xrun350 // check time vs timeout
403 // if( Digitalio::m_xrun == 0 )
404 if( time - g_watchdog_time < g_watchdog_timeout )351 if( time - g_watchdog_time < g_watchdog_timeout )
405 {352 {
406 // log353 // log
407 EM_log( CK_LOG_SEVERE, "real-time watchdog resting..." );354 EM_log( CK_LOG_SEVERE, "real-time watchdog resting..." );
408 // raise priority355 // raise priority
409 if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff )356 if( g_tid_synthesis && XThreadUtil::our_priority != 0x7fffffff )
410 set_priority( g_tid_synthesis, Chuck_VM::our_priority );357 XThreadUtil::set_priority( g_tid_synthesis, XThreadUtil::our_priority );
411 // set state358 // set state
412 g_watchdog_state = FALSE;359 g_watchdog_state = FALSE;
413 }360 }
@@ -428,9 +375,9 @@ static unsigned int __stdcall watch_dog( void * ) · 14 unmodified lines
428 375
429//-----------------------------------------------------------------------------376//-----------------------------------------------------------------------------
430// name: watchdog_start()377// name: watchdog_start()
431// desc: ...378// desc: start watchdog on separate thread
432//-----------------------------------------------------------------------------379//-----------------------------------------------------------------------------
433BOOL__ Digitalio::watchdog_start()380t_CKBOOL ChuckAudio::watchdog_start()
434{381{
435 // already382 // already
436 if( g_watchdog_thread )383 if( g_watchdog_thread )
@@ -448,11 +395,12 @@ BOOL__ Digitalio::watchdog_start() · 11 unmodified lines
448 395
449 396
450 397
398
451//-----------------------------------------------------------------------------399//-----------------------------------------------------------------------------
452// name: watchdog_stop()400// name: watchdog_stop()
453// desc: ...401// desc: stop watchdog thread
454//-----------------------------------------------------------------------------402//-----------------------------------------------------------------------------
455BOOL__ Digitalio::watchdog_stop()403t_CKBOOL ChuckAudio::watchdog_stop()
456{404{
457 // already405 // already
458 if( !g_watchdog_thread )406 if( !g_watchdog_thread )
@@ -460,8 +408,9 @@ BOOL__ Digitalio::watchdog_stop() · 1 unmodified line
460 408
461 // stop things409 // stop things
462 g_do_watchdog = FALSE;410 g_do_watchdog = FALSE;
463 // wait a bit411 // wait a bit | TODO: is this needed?
464 // usleep( 100000 )412 usleep( 100000 )
413 // delete watchdog thread | TODO: is this safe?
465 SAFE_DELETE( g_watchdog_thread );414 SAFE_DELETE( g_watchdog_thread );
466 415
467 return TRUE;416 return TRUE;
@@ -474,369 +423,273 @@ BOOL__ Digitalio::watchdog_stop() · 6 unmodified lines
474// name: initialize()423// name: initialize()
475// desc: ...424// desc: ...
476//-----------------------------------------------------------------------------425//-----------------------------------------------------------------------------
477BOOL__ Digitalio::initialize( DWORD__ num_dac_channels,426t_CKBOOL ChuckAudio::initialize( t_CKUINT num_dac_channels,
478 DWORD__ num_adc_channels,427 t_CKUINT num_adc_channels,
479 DWORD__ sampling_rate,428 t_CKUINT sample_rate,
480 DWORD__ bps, DWORD__ buffer_size, 429 t_CKUINT buffer_size,
481 DWORD__ num_buffers, DWORD__ block,430 t_CKUINT num_buffers,
482 Chuck_VM * vm_ref, BOOL__ rt_audio,431 f_audio_cb callback,
483 void * callback, void * data,432 void * data,
484 BOOL__ force_srate )433 t_CKBOOL force_srate )
485{434{
486 if( m_init )435 if( m_init )
487 return FALSE;436 return FALSE;
488 437
489 m_num_channels_out = num_dac_channels;438 m_num_channels_out = num_dac_channels;
490 m_num_channels_in = num_adc_channels;439 m_num_channels_in = num_adc_channels;
491 m_sampling_rate = sampling_rate;440 m_sample_rate = sample_rate;
492 m_bps = bps;
493 m_buffer_size = buffer_size;441 m_buffer_size = buffer_size;
494 m_num_buffers = num_buffers;442 m_num_buffers = num_buffers;
495 m_start = 0;443 m_start = 0;
496 m_tick_count = 0;
497 m_go = 0;444 m_go = 0;
498 m_end = 0;445 m_silent = 0;
499 m_block = block;446
500 447 // remember callback
501 DWORD__ num_channels;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
502 unsigned int bufsize = m_buffer_size;455 unsigned int bufsize = m_buffer_size;
503 456
504 // log457 // log
505 EM_log( CK_LOG_FINE, "initializing RtAudio..." );458 EM_log( CK_LOG_FINE, "initializing RtAudio..." );
506 // push indent459 // push indent
507 EM_pushlog();460 EM_pushlog();
508
509 // if rt_audio is false, then set block to FALSE to avoid deadlock
510 if( !rt_audio ) m_block = FALSE;
511 461
512#ifndef __DISABLE_RTAUDIO__ 462 // allocate RtAudio
513 // if real-time audio463 try { m_rtaudio = new RtAudio( ); }
514 if( rt_audio )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 )
515 {474 {
516 // allocate RtAudio475 // check output device number; 0 used to mean "default"
517 try { m_rtaudio = new RtAudio( ); }476 bool useDefault = ( m_dac_n == 0 );
518 catch( RtError err )477 // default (refactor 1.3.1.2)
478 if( useDefault )
519 {479 {
520 // problem finding audio devices, most likely480 // get the default
521 EM_error2( 0, "%s", err.getMessage().c_str() );481 m_dac_n = m_rtaudio->getDefaultOutputDevice();
522 return m_init = FALSE;
523 }482 }
524 483 else
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 )
528 {484 {
529 // check output device number; 0 used to mean "default"485 m_dac_n -= 1;
530 bool useDefault = ( m_dac_n == 0 );486 }
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 }
542 487
543 // get device info488 // get device info
544 RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_dac_n);489 RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_dac_n);
545 490
546 // ensure correct channel count if default device is requested491 // ensure correct channel count if default device is requested
547 if( useDefault )492 if( useDefault )
493 {
494 // check
495 if( device_info.outputChannels < m_num_channels_out )
548 {496 {
549 // check497 // find first device with at least the requested channel count
550 if( device_info.outputChannels < m_num_channels_out )498 m_dac_n = -1;
499 int num_devices = m_rtaudio->getDeviceCount();
500 for( int i = 0; i < num_devices; i++ )
551 {501 {
552 // find first device with at least the requested channel count502 device_info = m_rtaudio->getDeviceInfo(i);
553 m_dac_n = -1;503 if(device_info.outputChannels >= m_num_channels_out)
554 int num_devices = m_rtaudio->getDeviceCount();
555 for( int i = 0; i < num_devices; i++ )
556 {504 {
557 device_info = m_rtaudio->getDeviceInfo(i);505 m_dac_n = i;
558 if(device_info.outputChannels >= m_num_channels_out)506 break;
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;
570 }507 }
571 }508 }
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 }
572 }517 }
518 }
573 519
574 // index of closest sample rate520 // index of closest sample rate
575 long closestIndex = -1;521 long closestIndex = -1;
576 // difference of closest so far522 // difference of closest so far
577 long closestDiff = LONG_MAX;523 long closestDiff = LONG_MAX;
578 // the next highest524 // the next highest
579 long nextHighest = -1;525 long nextHighest = -1;
580 // diff to next highest so far526 // diff to next highest so far
581 long diffToNextHighest = LONG_MAX;527 long diffToNextHighest = LONG_MAX;
582 // check if request sample rate in support rates (added 1.3.1.2)528 // check if request sample rate in support rates (added 1.3.1.2)
583 for( long i = 0; i < device_info.sampleRates.size(); i++ )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 )
584 {535 {
585 // difference536 // remember index
586 long diff = device_info.sampleRates[i] - sampling_rate;537 closestIndex = i;
587 // check // ge: changed from abs to labs, 2015.11538 // update diff
588 if( ::labs(diff) < closestDiff )539 closestDiff = ::labs(diff);
589 {540 }
590 // remember index
591 closestIndex = i;
592 // update diff
593 closestDiff = ::labs(diff);
594 }
595 541
596 // for next highest542 // for next highest
597 if( diff > 0 && diff < diffToNextHighest )543 if( diff > 0 && diff < diffToNextHighest )
598 {544 {
599 // remember index545 // remember index
600 nextHighest = i;546 nextHighest = i;
601 // update diff547 // update diff
602 diffToNextHighest = diff;548 diffToNextHighest = diff;
603 }
604 }549 }
550 }
605 551
606 // see if we found exact match (added 1.3.1.2)552 // see if we found exact match (added 1.3.1.2)
607 if( closestDiff != 0 )553 if( closestDiff != 0 )
554 {
555 // check
556 if( force_srate )
608 {557 {
609 // check558 // request sample rate not found, error out
610 if( force_srate )559 EM_error2( 0, "unsupported sample rate (%d) requested...", sampling_rate );
611 {560 EM_error2( 0, "| (try --probe to enumerate available sample rates)" );
612 // request sample rate not found, error out561 return m_init = FALSE;
613 EM_error2( 0, "unsupported sample rate (%d) requested...", sampling_rate );562 }
614 EM_error2( 0, "| (try --probe to enumerate available sample rates)" );
615 return m_init = FALSE;
616 }
617 563
618 // use next highest if available564 // use next highest if available
619 if( nextHighest >= 0 )565 if( nextHighest >= 0 )
620 {566 {
621 // log567 // log
622 EM_log( CK_LOG_SEVERE, "new sample rate (next highest): %d -> %d",568 EM_log( CK_LOG_SEVERE, "new sample rate (next highest): %d -> %d",
623 sampling_rate, device_info.sampleRates[nextHighest] );569 sampling_rate, device_info.sampleRates[nextHighest] );
624 // update sampling rate570 // update sampling rate
625 m_sampling_rate = sampling_rate = device_info.sampleRates[nextHighest];571 m_sampling_rate = sampling_rate = device_info.sampleRates[nextHighest];
626 }572 }
627 else if( closestIndex >= 0 ) // nothing higher573 else if( closestIndex >= 0 ) // nothing higher
628 {574 {
629 // log575 // log
630 EM_log( CK_LOG_SEVERE, "new sample rate (closest): %d -> %d",576 EM_log( CK_LOG_SEVERE, "new sample rate (closest): %d -> %d",
631 sampling_rate, device_info.sampleRates[closestIndex] );577 sampling_rate, device_info.sampleRates[closestIndex] );
632 // update sampling rate578 // update sampling rate
633 m_sampling_rate = sampling_rate = device_info.sampleRates[closestIndex];579 m_sampling_rate = sampling_rate = device_info.sampleRates[closestIndex];
634 }580 }
635 else581 else
636 {582 {
637 // nothing to do (will fail and throw error message when opening)583 // nothing to do (will fail and throw error message when opening)
638 }
639 }584 }
640 }585 }
586 }
641 587
642 // convert 1-based ordinal to 0-based ordinal588 // convert 1-based ordinal to 0-based ordinal
643 if( m_num_channels_in > 0 )589 if( m_num_channels_in > 0 )
590 {
591 if( m_adc_n == 0 )
644 {592 {
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 )
646 {600 {
647 m_adc_n = m_rtaudio->getDefaultInputDevice();601 // find first device with at least the requested channel count
648 602 m_adc_n = -1;
649 // ensure correct channel count if default device is requested603 int num_devices = m_rtaudio->getDeviceCount();
650 RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_adc_n);604 for(int i = 0; i < num_devices; i++)
651
652 // check if input channels > 0
653 if( device_info.inputChannels < m_num_channels_in )
654 {605 {
655 // find first device with at least the requested channel count606 device_info = m_rtaudio->getDeviceInfo(i);
656 m_adc_n = -1;607 if(device_info.inputChannels >= m_num_channels_in)
657 int num_devices = m_rtaudio->getDeviceCount();
658 for(int i = 0; i < num_devices; i++)
659 {608 {
660 device_info = m_rtaudio->getDeviceInfo(i);609 m_adc_n = i;
661 if(device_info.inputChannels >= m_num_channels_in)610 break;
662 {
663 m_adc_n = i;
664 break;
665 }
666 }611 }
612 }
667 613
668 // changed 1.3.1.2 (ge): for input, if nothing found, we just gonna try to open half-duplex614 // 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 )615 if( m_adc_n == -1 )
670 {616 {
671 // set to 0617 // set to 0
672 m_num_channels_in = 0;618 m_num_channels_in = 0;
673 // problem finding audio devices, most likely619 // 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);620 // EM_error2( 0, "unable to find audio input device with requested channel count (%i)...",
675 // return m_init = FALSE;621 // m_num_channels_in);
676 }622 // return m_init = FALSE;
677 }623 }
678 }624 }
679 else
680 {
681 m_adc_n -= 1;
682 }
683 }625 }
684 626 else
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 )
724 {627 {
725 EM_log( CK_LOG_SEVERE, "new buffer size: %d -> %i", m_buffer_size, bufsize );628 m_adc_n -= 1;
726 m_buffer_size = bufsize;
727 }629 }
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;
739 }630 }
740#endif // __CHIP_MODE__
741 631
742 if( m_use_cb )632 // open device
743 {633 try {
744 num_channels = num_dac_channels > num_adc_channels ?
745 num_dac_channels : num_adc_channels;
746 // log634 // log
747 EM_log( CK_LOG_SEVERE, "allocating buffers for %d x %d samples...",635 EM_log( CK_LOG_FINE, "trying %d input %d output...",
748 m_buffer_size, num_channels );636 m_num_channels_in, m_num_channels_out );
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;
760 637
761 return m_init = TRUE;638 RtAudio::StreamParameters output_parameters;
762}639 output_parameters.deviceId = m_dac_n;
763 640 output_parameters.nChannels = m_num_channels_out;
764 641 output_parameters.firstChannel = 0;
765 642
766 643 RtAudio::StreamParameters input_parameters;
767//-----------------------------------------------------------------------------644 input_parameters.deviceId = m_adc_n;
768// name: cb()645 input_parameters.nChannels = m_num_channels_in;
769// desc: ...646 input_parameters.firstChannel = 0;
770//-----------------------------------------------------------------------------647
771//int Digitalio::cb( char * buffer, int buffer_size, void * user_data )648 RtAudio::StreamOptions stream_options;
772int Digitalio::cb( void *output_buffer, void *input_buffer,649 stream_options.flags = 0;
773 unsigned int buffer_size,650 stream_options.numberOfBuffers = num_buffers;
774 double streamTime,651 stream_options.streamName = "ChucK";
775 RtAudioStreamStatus status,652 stream_options.priority = 0;
776 void *user_data )653
777{654 // open RtAudio
778 DWORD__ len = buffer_size * sizeof(SAMPLE) * m_num_channels_out;655 m_rtaudio->openStream(
779 DWORD__ n = 20;656 m_num_channels_out > 0 ? &output_parameters : NULL,
780 DWORD__ start = 50;657 m_num_channels_in > 0 ? &input_parameters : NULL,
781 658 CK_RTAUDIO_FORMAT, sampling_rate, &bufsize,
782 // copy input to local buffer659 m_use_cb ? ( block ? &cb : &cb2 ) : NULL, vm_ref,
783 if( m_num_channels_in )660 &stream_options );
784 {661 } catch( RtError err ) {
785 memcpy( m_buffer_in, input_buffer, len );662 // log
786 // copy to extern663 EM_log( CK_LOG_INFO, "exception caught: '%s'...", err.getMessage().c_str() );
787 if( m_extern_in ) memcpy( m_extern_in, input_buffer, len );664 EM_error2( 0, "%s", err.getMessage().c_str() );
788 }665 SAFE_DELETE( m_rtaudio );
789 // flag ready666 return m_init = FALSE;
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 );
803 }667 }
804 else // initial condition668
669 // check bufsize
670 if( bufsize != (int)m_buffer_size )
805 {671 {
806 // priority boost672 EM_log( CK_LOG_SEVERE, "new buffer size: %d -> %i", m_buffer_size, bufsize );
807 if( !m_go && Chuck_VM::our_priority != 0x7fffffff )673 m_buffer_size = bufsize;
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;
818 }674 }
819 675
820 // 2nd buffer676 // pop indent
821 // RtAudio4 TODO677 EM_poplog();
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// }
830 678
831 // copy to extern679 // greater of dac/adc channels
832 if( m_extern_out ) memcpy( m_extern_out, output_buffer, len );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 );
833 685
834 // set pointer to the beginning - if not ready, then too late anyway686 // allocate buffers
835 //*m_write_ptr = (SAMPLE *)m_buffer_out;687 m_buffer_in = new SAMPLE[m_buffer_size * num_channels];
836 //*m_read_ptr = (SAMPLE *)m_buffer_in;688 m_buffer_out = new SAMPLE[m_buffer_size * num_channels];
837 m_out_ready = FALSE;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 );
838 691
839 return 0;692 return m_init = TRUE;
840}693}
841 694
842 695
@@ -846,15 +699,11 @@ int Digitalio::cb( void *output_buffer, void *input_buffer, · 3 unmodified lines
846// name: cb2()699// name: cb2()
847// desc: ...700// desc: ...
848//-----------------------------------------------------------------------------701//-----------------------------------------------------------------------------
849//int Digitalio::cb2( char * buffer, int buffer_size, void * user_data )702int ChuckAudio::cb( void * output_buffer, void * input_buffer, unsigned int buffer_size,
850int Digitalio::cb2( void *output_buffer, void *input_buffer,703 double streamTime, RtAudioStreamStatus status, void * user_data )
851 unsigned int buffer_size,
852 double streamTime,
853 RtAudioStreamStatus status,
854 void *user_data )
855{704{
856 DWORD__ len = buffer_size * sizeof(SAMPLE) * m_num_channels_out;705 // length, in bytes of output
857 Chuck_VM * vm_ref = (Chuck_VM *)user_data;706 t_CKUINT len = buffer_size * sizeof(SAMPLE) * m_num_channels_out;
858 707
859 // priority boost708 // priority boost
860 if( !m_go && Chuck_VM::our_priority != 0x7fffffff )709 if( !m_go && Chuck_VM::our_priority != 0x7fffffff )
@@ -876,7 +725,7 @@ int Digitalio::cb2( void *output_buffer, void *input_buffer, · 15 unmodified lines
876 725
877 // TODO: close the duplicate handle?726 // TODO: close the duplicate handle?
878#endif727#endif
879 Chuck_VM::set_priority( Chuck_VM::our_priority, NULL );728 XThreadUtil::set_priority( XThreadUtil::our_priority );
880 memset( output_buffer, 0, len );729 memset( output_buffer, 0, len );
881 m_go = TRUE;730 m_go = TRUE;
882 731
@@ -901,21 +750,11 @@ int Digitalio::cb2( void *output_buffer, void *input_buffer, · 18 unmodified lines
901 if( m_extern_in ) memcpy( m_extern_in, input_buffer, len );750 if( m_extern_in ) memcpy( m_extern_in, input_buffer, len );
902 }751 }
903 752
904 // check xrun753 // timestamp
905 if( m_xrun < 6 )754 if( g_do_watchdog ) g_watchdog_time = get_current_time( TRUE );
906 {755 // call the audio cb
907 // timestamp756 m_audio_cb( m_buffer_in, m_buffer_out, buffer_size,
908 if( g_do_watchdog ) g_watchdog_time = get_current_time( TRUE );757 m_num_channels_in, m_num_channels_out, m_cb_user_data );
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 }
919 758
920 // copy local buffer to be rendered759 // copy local buffer to be rendered
921 if( !m_end ) memcpy( output_buffer, m_buffer_out, len );760 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
925 // copy to extern764 // copy to extern
926 if( m_extern_out ) memcpy( m_extern_out, output_buffer, len );765 if( m_extern_out ) memcpy( m_extern_out, output_buffer, len );
927 766
928
929 return 0;767 return 0;
930}768}
931 769
932 770
933 771
934 772
935#ifdef __CHIP_MODE__
936//-----------------------------------------------------------------------------
937// name: MoAudio_cb()
938// desc: ...
939//-----------------------------------------------------------------------------
940void 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
949//-----------------------------------------------------------------------------773//-----------------------------------------------------------------------------
950// name: start()774// name: start()
951// desc: ...775// desc: start host audio
952//-----------------------------------------------------------------------------776//-----------------------------------------------------------------------------
953BOOL__ Digitalio::start( )777t_CKBOOL ChuckAudio::start( )
954{778{
955#ifndef __DISABLE_RTAUDIO__779 try {
956 try{ if( !m_start )780 if( !m_start )
957 m_rtaudio->startStream();781 m_rtaudio->startStream();
958 m_start = TRUE;782 m_start = TRUE;
959 } catch( RtError err ){ return FALSE; }783 }
960#endif // __DISABLE_RTAUDIO__784 catch( RtError err )
961 785 {
962#if defined(__CHIP_MODE__)786 return FALSE;
963 if( !m_start )787 }
964 m_start = MoAudio::start( MoAudio_cb, g_vm );
965#endif // __CHIP_MODE__
966 788
967 return m_start;789 return m_start;
968}790}
@@ -972,22 +794,22 @@ BOOL__ Digitalio::start( ) · 3 unmodified lines
972 794
973//-----------------------------------------------------------------------------795//-----------------------------------------------------------------------------
974// name: stop()796// name: stop()
975// desc: ...797// desc: stop host audio
976//-----------------------------------------------------------------------------798//-----------------------------------------------------------------------------
977BOOL__ Digitalio::stop( )799t_CKBOOL ChuckAudio::stop( )
978{800{
979#ifndef __DISABLE_RTAUDIO__801 try {
980 try{ if( m_start )802 if( m_start )
981 m_rtaudio->stopStream();803 m_rtaudio->stopStream();
982 m_start = FALSE;804 m_start = FALSE;
983 } catch( RtError err ){ return FALSE; }805 }
984#endif // __DISABLE_RTAUDIO__806 catch( RtError err )
985 807 {
986#if defined(__CHIP_MODE__)808 return FALSE;
987 if( m_start )809 }
988 MoAudio::stop();810
989 m_start = FALSE;811 // REFACTOR-2017: set end flag
990#endif812 m_silent = TRUE;
991 813
992 return !m_start;814 return !m_start;
993}815}
@@ -995,701 +817,33 @@ BOOL__ Digitalio::stop( ) · 1 unmodified line
995 817
996 818
997 819
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
1025//-----------------------------------------------------------------------------820//-----------------------------------------------------------------------------
1026// name: shutdown()821// name: shutdown()
1027// desc: ...822// desc: ...
1028//-----------------------------------------------------------------------------823//-----------------------------------------------------------------------------
1029void Digitalio::shutdown()824void ChuckAudio::shutdown()
1030{825{
826 // check flag
1031 if( !m_init ) return;827 if( !m_init ) return;
1032 828
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
1034 if( m_start )834 if( m_start )
1035 {835 {
1036 //if( m_use_cb ) m_rtaudio->cancelStreamCallback();836 // m_rtaudio->cancelStreamCallback();
1037 m_rtaudio->stopStream();837 // m_rtaudio->stopStream();
838 stop();
1038 }839 }
1039 840
841 // close stream
1040 m_rtaudio->closeStream();842 m_rtaudio->closeStream();
843 // cleanup
1041 SAFE_DELETE( m_rtaudio );844 SAFE_DELETE( m_rtaudio );
1042#endif // __DISABLE_RTAUDIO__
1043 845
846 // unflag
1044 m_init = FALSE;847 m_init = FALSE;
1045 m_start = FALSE;848 m_start = FALSE;
1046
1047 // stop watchdog
1048 watchdog_stop();
1049}
1050
1051
1052
1053
1054//-----------------------------------------------------------------------------
1055// name: DigitalOut()
1056// desc: ...
1057//-----------------------------------------------------------------------------
1058DigitalOut::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//-----------------------------------------------------------------------------
1071DigitalOut::~DigitalOut()
1072{
1073 this->cleanup();
1074}
1075
1076
1077
1078
1079//-----------------------------------------------------------------------------
1080// name: initialize()
1081// desc: initialize audio out
1082//-----------------------------------------------------------------------------
1083BOOL__ 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//-----------------------------------------------------------------------------
1111BOOL__ DigitalOut::start()
1112{
1113 // start stream
1114 return ( Digitalio::start() != 0 );
1115}
1116
1117
1118
1119
1120//-----------------------------------------------------------------------------
1121// name: stop()
1122// desc: render
1123//-----------------------------------------------------------------------------
1124BOOL__ DigitalOut::stop()
1125{
1126 // well
1127 Digitalio::stop();
1128
1129 return TRUE;
1130}
1131
1132
1133
1134
1135//-----------------------------------------------------------------------------
1136// name: cleanup()
1137// desc: ...
1138//-----------------------------------------------------------------------------
1139void DigitalOut::cleanup()
1140{
1141}
1142
1143
1144
1145
1146//-----------------------------------------------------------------------------
1147// name: tick_out()
1148// desc: 1 channel
1149//-----------------------------------------------------------------------------
1150BOOL__ 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//-----------------------------------------------------------------------------
1167BOOL__ 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//-----------------------------------------------------------------------------
1185BOOL__ 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//-----------------------------------------------------------------------------
1204inline 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//-----------------------------------------------------------------------------
1221DWORD__ 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//-----------------------------------------------------------------------------
1247DigitalIn::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//-----------------------------------------------------------------------------
1260DigitalIn::~DigitalIn()
1261{
1262 this->cleanup();
1263}
1264
1265
1266
1267
1268//-----------------------------------------------------------------------------
1269// name: initialize()
1270// desc: initialize audio in
1271//-----------------------------------------------------------------------------
1272BOOL__ 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//-----------------------------------------------------------------------------
1304BOOL__ DigitalIn::start()
1305{
1306 return ( Digitalio::start() != 0 );
1307}
1308
1309
1310
1311
1312//-----------------------------------------------------------------------------
1313// name: capture_stop()
1314// desc: ...
1315//-----------------------------------------------------------------------------
1316BOOL__ DigitalIn::stop()
1317{
1318 Digitalio::stop();
1319 return TRUE;
1320}
1321
1322
1323
1324
1325//-----------------------------------------------------------------------------
1326// name: cleanup()
1327// desc: ...
1328//-----------------------------------------------------------------------------
1329void DigitalIn::cleanup()
1330{
1331}
1332
1333
1334
1335
1336//-----------------------------------------------------------------------------
1337// name: tick_in()
1338// desc: ...
1339//-----------------------------------------------------------------------------
1340BOOL__ 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//-----------------------------------------------------------------------------
1356BOOL__ 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//-----------------------------------------------------------------------------
1374BOOL__ 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//-----------------------------------------------------------------------------
1393inline 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//-----------------------------------------------------------------------------
1410DWORD__ 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//-----------------------------------------------------------------------------
1438AudioBufferX::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//-----------------------------------------------------------------------------
1456BOOL__ 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//-----------------------------------------------------------------------------
1481void 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//-----------------------------------------------------------------------------
1500DWORD__ AudioBufferX::size()
1501{
1502 return m_size;
1503}
1504
1505
1506
1507
1508//-----------------------------------------------------------------------------
1509// name: data()
1510// desc: ...
1511//-----------------------------------------------------------------------------
1512SAMPLE * AudioBufferX::data()
1513{
1514 return m_data;
1515}
1516
1517
1518
1519
1520//-----------------------------------------------------------------------------
1521// name: AudioBufferIn()
1522// desc: ...
1523//-----------------------------------------------------------------------------
1524AudioBufferIn::AudioBufferIn( DWORD__ size )
1525 : AudioBufferX( size )
1526{ }
1527
1528
1529
1530
1531//-----------------------------------------------------------------------------
1532// name: ~AudioBufferIn()
1533// desc: ...
1534//-----------------------------------------------------------------------------
1535AudioBufferIn::~AudioBufferIn()
1536{
1537 this->cleanup();
1538}
1539
1540
1541
1542
1543//-----------------------------------------------------------------------------
1544// name: reset()
1545// desc: ...
1546//-----------------------------------------------------------------------------
1547BOOL__ 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//-----------------------------------------------------------------------------
1561BOOL__ 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//-----------------------------------------------------------------------------
1578BOOL__ 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//-----------------------------------------------------------------------------
1596BOOL__ 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//-----------------------------------------------------------------------------
1614AudioBufferOut::AudioBufferOut( DWORD__ size )
1615 : AudioBufferX( size )
1616{ }
1617
1618
1619
1620
1621//-----------------------------------------------------------------------------
1622// name: ~AudioBufferOut()
1623// desc: ...
1624//-----------------------------------------------------------------------------
1625AudioBufferOut::~AudioBufferOut()
1626{
1627 this->cleanup();
1628}
1629
1630
1631
1632
1633//-----------------------------------------------------------------------------
1634// name: reset()
1635// desc: ...
1636//-----------------------------------------------------------------------------
1637BOOL__ 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//-----------------------------------------------------------------------------
1651BOOL__ 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//-----------------------------------------------------------------------------
1668BOOL__ 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//-----------------------------------------------------------------------------
1686BOOL__ 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;
1695}849}
src/host/chuck_audio.h+78−304
@@ -23,351 +23,125 @@ · 22 unmodified lines
23-----------------------------------------------------------------------------*/23-----------------------------------------------------------------------------*/
24 24
25//-----------------------------------------------------------------------------25//-----------------------------------------------------------------------------
26// name: digiio_rtaudio.h26// name: chuck_audio.h
27// desc: digitalio over RtAudio (from Gary Scavone)27// desc: chuck host digital audio I/O, using RtAudio (from Gary Scavone)
28//28//
29// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)29// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30// Spencer Salazar (spencer@ccrma.stanford.edu)30// Spencer Salazar (spencer@ccrma.stanford.edu)
31// RtAudio by: Gary Scavone31// RtAudio by: Gary Scavone
32// date: Spring 200432// date: Spring 2004
33//-----------------------------------------------------------------------------33//-----------------------------------------------------------------------------
34#ifndef __DIGITAL_IO_H__34#ifndef __CHUCK_AUDIO_H__
35#define __DIGITAL_IO_H__35#define __CHUCK_AUDIO_H__
36 36
37#include "chuck_def.h"37#include "chuck_def.h"
38#include <string>38#include <string>
39#ifndef __CHIP_MODE__
40#include "RtAudio/RtAudio.h"39#include "RtAudio/RtAudio.h"
41#else
42class RtAudio;
43typedef unsigned int RtAudioStreamStatus;
44#endif // __CHIP_MODE__
45 40
46 41
47 42
48 43
49//-----------------------------------------------------------------------------44//-----------------------------------------------------------------------------
50// define and forward references45// define, defaults, forward references
51//-----------------------------------------------------------------------------46//-----------------------------------------------------------------------------
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
64#define NUM_CHANNELS_DEFAULT 2 // number of channels47#define NUM_CHANNELS_DEFAULT 2 // number of channels
65 #if defined(__PLATFORM_LINUX__)48#define NUM_BUFFERS_DEFAULT 8 // number buffers
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
73#define DEVICE_NUM_OUT_DEFAULT 049#define DEVICE_NUM_OUT_DEFAULT 0
74#define DEVICE_NUM_IN_DEFAULT 050#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
75 62
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
93 63
94 64
95#ifndef FALSE
96 #define FALSE 0
97#endif
98#ifndef TRUE
99 #define TRUE 1
100#endif
101 65
102class RtAudio;66// audio callback definition
103struct Chuck_VM;67void (* f_audio_cb)( SAMPLE * input, SAMPLE * output, t_CKUINT numFrames,
68 t_CKUINT numInChans, t_CKUINT numOutChans, void * userData );
104 69
105 70
106 71
107 72
108//-----------------------------------------------------------------------------73//-----------------------------------------------------------------------------
109// name: Digitalio74// name: class ChuckAudio
110// desc: ...75// desc: chuck host audio I/O
111//-----------------------------------------------------------------------------76//-----------------------------------------------------------------------------
112class Digitalio77class ChuckAudio
113{78{
114public:79public:
115 static BOOL__ initialize( DWORD__ num_dac_channels,80 static t_CKBOOL initialize( t_CKUINT num_dac_channels,
116 DWORD__ num_adc_channels,81 t_CKUINT num_adc_channels,
117 DWORD__ sampling_rate,82 t_CKUINT sample_rate,
118 DWORD__ bps,83 t_CKUINT buffer_size,
119 DWORD__ buffer_size,84 t_CKUINT num_buffers,
120 DWORD__ num_buffers,85 f_audio_cb callback,
121 DWORD__ block,86 void * data,
122 Chuck_VM * vm_ref,87 // force_srate added 1.3.1.2
123 BOOL__ rt_audio,88 t_CKBOOL force_srate );
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();
130 static void shutdown();89 static void shutdown();
131 static void probe();90 static t_CKBOOL start();
132 91 static t_CKBOOL stop();
133 static DWORD__ device_named( const std::string & name, t_CKBOOL needs_dac = FALSE, t_CKBOOL needs_adc = FALSE );
134 92
135public:93public: // watchdog stuff
136 static DWORD__ sampling_rate( ) { return m_sampling_rate; }94 static t_CKBOOL watchdog_start();
137 static DWORD__ num_channels_out( ) { return m_num_channels_out; }95 static t_CKBOOL watchdog_stop();
138 static DWORD__ num_channels_in( ) { return m_num_channels_in; }96
139 static DWORD__ dac_num( ) { return m_dac_n; }97public: // device info
140 static DWORD__ adc_num( ) { return m_adc_n; }98 // probe audio devices
141 static DWORD__ bps( ) { return m_bps; }99 static void probe();
142 static DWORD__ buffer_size( ) { return m_buffer_size; }100 // get device number by name?
143 static DWORD__ num_buffers( ) { return m_num_buffers; }101 static t_CKUINT device_named( const std::string & name,
144 static RtAudio * audio( ) { return m_rtaudio; }102 t_CKBOOL needs_dac = FALSE,
145 static BOOL__ start( );103 t_CKBOOL needs_adc = FALSE );
146 static BOOL__ stop( );104
147 //static BOOL__ tick( );105public:
148 static void set_extern( SAMPLE * in, SAMPLE * out )106 static t_CKUINT srate() { return m_sample_rate; }
149 { m_extern_in = in; m_extern_out = out; } 107 static t_CKUINT num_channels_out() { return m_num_channels_out; }
150 static int cb( void *output_buffer, void *input_buffer,108 static t_CKUINT num_channels_in() { return m_num_channels_in; }
151 unsigned int buffer_size,109 static t_CKUINT dac_num() { return m_dac_n; }
152 double streamTime,110 static t_CKUINT adc_num() { return m_adc_n; }
153 RtAudioStreamStatus status,111 static t_CKUINT bps() { return m_bps; }
154 void *user_data );112 static t_CKUINT buffer_size() { return m_buffer_size; }
155 static int cb2( void *output_buffer, void *input_buffer,113 static t_CKUINT num_buffers() { return m_num_buffers; }
156 unsigned int buffer_size,114 static RtAudio * audio() { return m_rtaudio; }
157 double streamTime,115
158 RtAudioStreamStatus status,116 static void set_extern( SAMPLE * in, SAMPLE * out )
159 void *user_data );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 );
160 120
161public: // data121public: // data
162 static BOOL__ m_init;122 static t_CKBOOL m_init;
163 static DWORD__ m_start;123 static t_CKBOOL m_start;
164 static DWORD__ m_tick_count;124 static t_CKBOOL m_go; // counter of # of times callback called
165 static DWORD__ m_num_channels_out;125 static t_CKBOOL m_silent; // if true, will output silence
166 static DWORD__ m_num_channels_in;126 static t_CKUINT m_num_channels_out;
167 static DWORD__ m_sampling_rate;127 static t_CKUINT m_num_channels_in;
168 static DWORD__ m_bps;128 static t_CKUINT m_sample_rate;
169 static DWORD__ m_buffer_size;129 static t_CKUINT m_bps;
170 static DWORD__ m_num_buffers;130 static t_CKUINT m_buffer_size;
171 static RtAudio * m_rtaudio;131 static t_CKUINT m_num_buffers;
172 static SAMPLE * m_buffer_out;132 static SAMPLE * m_buffer_out;
173 static SAMPLE * m_buffer_in;133 static SAMPLE * m_buffer_in;
174 static SAMPLE ** m_write_ptr;134 static SAMPLE * m_extern_in; // for things like audicle
175 static SAMPLE ** m_read_ptr;135 static SAMPLE * m_extern_out; // for things like audicle
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//-----------------------------------------------------------------------------
197class TickOut
198{
199public:
200 virtual ~TickOut() {}
201
202public:
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//-----------------------------------------------------------------------------
216class TickIn
217{
218public:
219 virtual ~TickIn() { }
220
221public:
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//-----------------------------------------------------------------------------
239class DigitalOut : public TickOut
240{
241public:
242 DigitalOut();
243 ~DigitalOut();
244
245public:
246 BOOL__ initialize();
247 void cleanup();
248
249 BOOL__ start();
250 BOOL__ stop();
251
252public:
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
257public:
258 DWORD__ render();
259
260protected:
261 SAMPLE * m_data_ptr_out;
262 SAMPLE * m_data_max_out;
263 136
264 inline BOOL__ prepare_tick_out();137 static RtAudio * m_rtaudio;
265};138 static t_CKUINT m_dac_n;
266 139 static t_CKUINT m_adc_n;
267 140 static f_audio_cb m_audio_cb;
268 141 static void * m_cb_user_data;
269
270//-----------------------------------------------------------------------------
271// name: class DigitalIn
272// desc: ...
273//-----------------------------------------------------------------------------
274class DigitalIn : public TickIn
275{
276public:
277 DigitalIn();
278 ~DigitalIn();
279
280public: // in
281 BOOL__ initialize();
282 void cleanup();
283
284 BOOL__ start();
285 BOOL__ stop();
286
287public:
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
292public:
293 DWORD__ capture( );
294
295protected:
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//-----------------------------------------------------------------------------
310class AudioBufferX
311{
312public:
313 AudioBufferX( DWORD__ size = 0 );
314
315public:
316 BOOL__ initialize( DWORD__ size );
317 void cleanup();
318 SAMPLE * data();
319 DWORD__ size();
320
321protected:
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//-----------------------------------------------------------------------------
336class AudioBufferIn : public TickIn, public AudioBufferX
337{
338public:
339 AudioBufferIn( DWORD__ size = 0 );
340 virtual ~AudioBufferIn();
341
342public:
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//-----------------------------------------------------------------------------
356class AudioBufferOut : public TickOut, public AudioBufferX
357{
358public:
359 AudioBufferOut( DWORD__ size = 0 );
360 virtual ~AudioBufferOut();
361
362public:
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 );
367};142};
368 143
369 144
370 145
371 146
372#endif147#endif
373
src/host/chuck_main.cpp+1172−10
@@ -24,25 +24,1187 @@ · 23 unmodified lines
24 24
25//-----------------------------------------------------------------------------25//-----------------------------------------------------------------------------
26// file: chuck_main.cpp26// file: chuck_main.cpp
27// desc: chuck entry point27// desc: chuck entry point | command line host
28//28//
29// v1.3.5.3: migration to chuck_system.* (see for more details)29// v1.3.5.3: migration to chuck_system.* (see for more details)
30//30//
31// author: Ge Wang (http://www.gewang.com/)31// author: Ge Wang | http://www.gewang.com/
32// (see chuck_system.*)32// (see chuck_system.*)
33//-----------------------------------------------------------------------------33//-----------------------------------------------------------------------------
34#include "chuck_system.h"34#include "chuck.h"
35#include "chuck_audio.h"
35 36
36#ifndef __ALTER_ENTRY_POINT__37
37int main( int argc, const char ** argv )38
39
40// function prototypes
41t_CKBOOL init_shell( Chuck_Shell * shell, Chuck_Shell_UI * ui, Chuck_VM * vm );
42void global_cleanup();
43void usage();
44void uh();
45t_CKBOOL get_count( const char * arg, t_CKUINT * out );
46void cb( t_CKSAMPLE * in, t_CKSAMPLE * out, t_CKUINT numFrames,
47 t_CKUINT numInChans, t_CKUINT numOutChans, void * data );
48
49// C functions
50extern "C" void signal_int( int sig_num );
51
52
53// the one ChucK, for command line host
54ChucK * the_chuck;
55// thread id for shell
56CHUCK_THREAD g_tid_shell = 0;
57// default destination host name
58char g_otf_dest[256] = "127.0.0.1";
59
60// the shell
61Chuck_Shell * g_shell = NULL;
62// global variables
63t_CKUINT g_sigpipe_mode = 0;
64// real-time watch dog
65t_CKBOOL g_do_watchdog = FALSE;
66// countermeasure
67#ifdef __MACOSX_CORE__
68t_CKUINT g_watchdog_countermeasure_priority = 10;
69#elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__)
70t_CKUINT g_watchdog_countermeasure_priority = THREAD_PRIORITY_LOWEST;
38#else71#else
39extern "C" int chuck_main( int argc, const char ** argv )72t_CKUINT g_watchdog_countermeasure_priority = 0;
40#endif73#endif
74// watchdog timeout
75t_CKFLOAT g_watchdog_timeout = 0.5;
76// thread id for whatever
77CHUCK_THREAD g_tid_whatever = 0;
78// flag for Std.system( string )
79t_CKBOOL g_enable_system_cmd = FALSE;
80// flag for enabling shell, ge: 1.3.5.3
81t_CKBOOL g_enable_shell = FALSE;
82// flag for audio enable, ge: 1.3.5.3
83t_CKBOOL g_enable_realtime_audio = TRUE;
84// added 1.3.2.0 // moved from VM 1.3.5.3
85f_mainthreadhook g_main_thread_hook = NULL;
86f_mainthreadquit g_main_thread_quit = NULL;
87void * g_main_thread_bindle = NULL;
88// num vms running; used to quit le_cb thread // added 1.3.6.0
89t_CKUINT g_num_vms_running = 0;
90
91
92
93
94//-----------------------------------------------------------------------------
95// name: main()
96// desc: ...
97//-----------------------------------------------------------------------------
98int main( int argc, const char ** argv )
41{99{
42 // chuck system100 // parse, init, run!
43 Chuck_System chuck;101 go( argc, argv );
44 // do it102
45 chuck.go( argc, argv );103 // clean up
104 global_cleanup();
46 105
47 return 0;106 return 0;
48}107}
108
109
110
111
112//-----------------------------------------------------------------------------
113// name: cb()
114// desc: audio callback
115//-----------------------------------------------------------------------------
116void 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//-----------------------------------------------------------------------------
132static 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//-----------------------------------------------------------------------------
173static 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//-----------------------------------------------------------------------------
195static 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//-----------------------------------------------------------------------------
220extern "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//-----------------------------------------------------------------------------
237void 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//-----------------------------------------------------------------------------
305static 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//-----------------------------------------------------------------------------
331bool 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