1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: digiio_rtaudio.cpp
27 // desc: digitalio over rtaudio (from Gary Scavone)
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 //-----------------------------------------------------------------------------
32 #include "digiio_rtaudio.h"
34 #include "chuck_errmsg.h"
35 #include "chuck_globals.h"
36 #ifndef __DISABLE_RTAUDIO__
38 #endif // __DISABLE_RTAUDIO__
39 #if defined(__CHIP_MODE__)
40 #include "../small.h">
41 #endif // __CHIP_MODE__
42 #ifndef __DISABLE_MIDI__
44 #endif // __DISABLE_MIDI__
45 // #include <signal.h>
46 #if (defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)) && !defined(__WINDOWS_PTHREAD__)
48 #include <sys/timeb.h>
54 // extern "C" void signal_int( int );
57 BOOL__
Digitalio::m_init
= FALSE
;
58 DWORD__
Digitalio::m_start
= 0;
59 DWORD__
Digitalio::m_tick_count
= 0;
60 DWORD__
Digitalio::m_num_channels_out
= NUM_CHANNELS_DEFAULT
;
61 DWORD__
Digitalio::m_num_channels_in
= NUM_CHANNELS_DEFAULT
;
62 DWORD__
Digitalio::m_sampling_rate
= SAMPLING_RATE_DEFAULT
;
63 DWORD__
Digitalio::m_bps
= BITS_PER_SAMPLE_DEFAULT
;
64 DWORD__
Digitalio::m_buffer_size
= BUFFER_SIZE_DEFAULT
;
65 DWORD__
Digitalio::m_num_buffers
= NUM_BUFFERS_DEFAULT
;
66 RtAudio
* Digitalio::m_rtaudio
= NULL
;
67 SAMPLE
* Digitalio::m_buffer_out
= NULL
;
68 SAMPLE
* Digitalio::m_buffer_in
= NULL
;
69 SAMPLE
** Digitalio::m_write_ptr
= NULL
;
70 SAMPLE
** Digitalio::m_read_ptr
= NULL
;
71 SAMPLE
* Digitalio::m_extern_in
= NULL
;
72 SAMPLE
* Digitalio::m_extern_out
= NULL
;
73 BOOL__
Digitalio::m_out_ready
= FALSE
;
74 BOOL__
Digitalio::m_in_ready
= FALSE
;
75 BOOL__
Digitalio::m_use_cb
= USE_CB_DEFAULT
;
76 DWORD__
Digitalio::m_go
= 0;
77 DWORD__
Digitalio::m_dac_n
= 0;
78 DWORD__
Digitalio::m_adc_n
= 0;
79 DWORD__
Digitalio::m_end
= 0;
80 DWORD__
Digitalio::m_block
= TRUE
;
81 DWORD__
Digitalio::m_xrun
= 0;
85 #if defined(CK_S_DOUBLE)
86 #define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT64
88 #define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT32
94 #ifndef __DISABLE_RTAUDIO__
95 //-----------------------------------------------------------------------------
98 //-----------------------------------------------------------------------------
99 void print( const RtAudioDeviceInfo
& info
)
101 EM_error2b( 0, "device name = \"%s\"", info
.name
.c_str() );
102 if (info
.probed
== false)
103 EM_error2b( 0, "probe [failed] ..." );
106 EM_error2b( 0, "probe [success] ..." );
107 EM_error2b( 0, "# output channels = %d", info
.outputChannels
);
108 EM_error2b( 0, "# input channels = %d", info
.inputChannels
);
109 EM_error2b( 0, "# duplex Channels = %d", info
.duplexChannels
);
110 if( info
.isDefault
) EM_error2b( 0, "default device = YES" );
111 else EM_error2b( 0, "default device = NO" );
112 if( info
.nativeFormats
== 0 ) EM_error2b( 0, "no natively supported data formats(?)!" );
115 EM_error2b( 0, "natively supported data formats:" );
116 if( info
.nativeFormats
& RTAUDIO_SINT8
) EM_error2b( 0, " 8-bit int" );
117 if( info
.nativeFormats
& RTAUDIO_SINT16
) EM_error2b( 0, " 16-bit int" );
118 if( info
.nativeFormats
& RTAUDIO_SINT24
) EM_error2b( 0, " 24-bit int" );
119 if( info
.nativeFormats
& RTAUDIO_SINT32
) EM_error2b( 0, " 32-bit int" );
120 if( info
.nativeFormats
& RTAUDIO_FLOAT32
) EM_error2b( 0, " 32-bit float" );
121 if( info
.nativeFormats
& RTAUDIO_FLOAT64
) EM_error2b( 0, " 64-bit float" );
123 if ( info
.sampleRates
.size() < 1 ) EM_error2b( 0,"no supported sample rates found!" );
126 EM_error2b( 0, "supported sample rates:" );
127 for( unsigned int j
= 0; j
< info
.sampleRates
.size(); j
++ )
128 EM_error2b( 0, " %d Hz", info
.sampleRates
[j
] );
132 #endif // __DISABLE_RTAUDIO__
137 //-----------------------------------------------------------------------------
140 //-----------------------------------------------------------------------------
141 void Digitalio::probe()
143 #ifndef __DISABLE_RTAUDIO__
144 RtAudio
* rta
= NULL
;
145 RtAudioDeviceInfo info
;
148 try { rta
= new RtAudio( ); }
151 // problem finding audio devices, most likely
152 EM_error2b( 0, "%s", err
.getMessageString() );
157 int devices
= rta
->getDeviceCount();
158 EM_error2b( 0, "found %d device(s) ...", devices
);
159 // EM_error2( 0, "--------------------------" );
162 for( int i
= 1; i
<= devices
; i
++ )
164 try { info
= rta
->getDeviceInfo(i
); }
165 catch( RtError
& error
)
167 error
.printMessage();
172 EM_error2b( 0, "------( chuck -- dac%d )---------------", i
);
175 if( i
< devices
) EM_error2( 0, "" );
179 #endif // __DISABLE_RTAUDIO__
187 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
188 //-----------------------------------------------------------------------------
189 // name: set_priority()
191 //-----------------------------------------------------------------------------
192 static t_CKBOOL
set_priority( CHUCK_THREAD tid
, t_CKINT priority
)
194 struct sched_param param
;
198 EM_log( CK_LOG_FINE
, "setting thread priority to: %ld...", priority
);
201 if( pthread_getschedparam( tid
, &policy
, ¶m
) )
205 param
.sched_priority
= priority
;
209 if( pthread_setschedparam( tid
, policy
, ¶m
) )
215 //-----------------------------------------------------------------------------
216 // name: set_priority()
218 //-----------------------------------------------------------------------------
219 static t_CKBOOL
set_priority( CHUCK_THREAD tid
, t_CKINT priority
)
221 // if priority is 0 then done
222 if( !priority
) return TRUE
;
225 EM_log( CK_LOG_FINE
, "setting thread priority to: %ld...", priority
);
227 // set the priority the thread
228 if( !SetThreadPriority( tid
, priority
) )
236 //-----------------------------------------------------------------------------
237 // name: get_current_time()
239 //-----------------------------------------------------------------------------
240 static t_CKFLOAT
get_current_time( t_CKBOOL fresh
= TRUE
)
242 #ifdef __PLATFORM_WIN32__
245 return t
.time
+ t
.millitm
/1000.0;
247 static struct timeval t
;
248 if( fresh
) gettimeofday(&t
,NULL
);
249 return t
.tv_sec
+ (t_CKFLOAT
)t
.tv_usec
/1000000;
257 static CHUCK_THREAD g_tid_synthesis
= 0;
258 static XThread
* g_watchdog_thread
= NULL
;
259 static t_CKBOOL g_watchdog_state
= FALSE
;
260 static t_CKFLOAT g_watchdog_time
= 0;
263 //-----------------------------------------------------------------------------
266 //-----------------------------------------------------------------------------
267 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
268 static void * watch_dog( void * )
270 static unsigned int __stdcall
watch_dog( void * )
276 t_CKUINT priority
= Chuck_VM::our_priority
;
279 EM_log( CK_LOG_SEVERE
, "starting real-time watch dog processs..." );
282 EM_log( CK_LOG_INFO
, "watchdog timeout: %f::second", g_watchdog_timeout
);
283 EM_log( CK_LOG_INFO
, "watchdog thread priority: %d", priority
);
284 EM_log( CK_LOG_INFO
, "watchdog countermeasure priority: %d", g_watchdog_countermeasure_priority
);
288 // boost watchdog by same priority
289 if( Chuck_VM::our_priority
!= 0x7fffffff )
290 Chuck_VM::set_priority( priority
, NULL
);
293 while( g_do_watchdog
)
296 time
= get_current_time( TRUE
);
297 // fprintf( stderr, "last: %f now: %f\n", g_watchdog_time, time );
300 if( g_watchdog_state
== FALSE
)
303 // if( Digitalio::m_xrun > 100 )
304 if( time
- g_watchdog_time
> g_watchdog_timeout
)
307 EM_log( CK_LOG_SEVERE
, "real-time watchdog counter-measure activating..." );
309 if( g_tid_synthesis
&& Chuck_VM::our_priority
!= 0x7fffffff )
310 set_priority( g_tid_synthesis
, g_watchdog_countermeasure_priority
);
312 g_watchdog_state
= TRUE
;
318 // if( Digitalio::m_xrun == 0 )
319 if( time
- g_watchdog_time
< g_watchdog_timeout
)
322 EM_log( CK_LOG_SEVERE
, "real-time watchdog resting..." );
324 if( g_tid_synthesis
&& Chuck_VM::our_priority
!= 0x7fffffff )
325 set_priority( g_tid_synthesis
, Chuck_VM::our_priority
);
327 g_watchdog_state
= FALSE
;
336 EM_log( CK_LOG_SEVERE
, "stopping real-time watch dog process..." );
344 //-----------------------------------------------------------------------------
345 // name: watchdog_start()
347 //-----------------------------------------------------------------------------
348 BOOL__
Digitalio::watchdog_start()
351 if( g_watchdog_thread
)
355 g_do_watchdog
= TRUE
;
357 g_watchdog_thread
= new XThread
;
359 g_watchdog_thread
->start( watch_dog
, NULL
);
366 //-----------------------------------------------------------------------------
367 // name: watchdog_stop()
369 //-----------------------------------------------------------------------------
370 BOOL__
Digitalio::watchdog_stop()
373 if( !g_watchdog_thread
)
377 g_do_watchdog
= FALSE
;
380 SAFE_DELETE( g_watchdog_thread
);
388 //-----------------------------------------------------------------------------
389 // name: initialize()
391 //-----------------------------------------------------------------------------
392 BOOL__
Digitalio::initialize( DWORD__ num_dac_channels
,
393 DWORD__ num_adc_channels
,
394 DWORD__ sampling_rate
,
395 DWORD__ bps
, DWORD__ buffer_size
,
396 DWORD__ num_buffers
, DWORD__ block
,
397 Chuck_VM
* vm_ref
, BOOL__ rt_audio
,
398 void * callback
, void * data
)
403 m_num_channels_out
= num_dac_channels
;
404 m_num_channels_in
= num_adc_channels
;
405 m_sampling_rate
= sampling_rate
;
407 m_buffer_size
= buffer_size
;
408 m_num_buffers
= num_buffers
;
415 DWORD__ num_channels
;
416 int bufsize
= m_buffer_size
;
418 // if rt_audio is false, then set block to FALSE to avoid deadlock
419 if( !rt_audio
) m_block
= FALSE
;
421 #ifndef __DISABLE_RTAUDIO__
422 // if real-time audio
426 try { m_rtaudio
= new RtAudio( ); }
429 // problem finding audio devices, most likely
430 EM_error2( 0, "%s", err
.getMessageString() );
431 return m_init
= FALSE
;
435 EM_log( CK_LOG_FINE
, "initializing RtAudio..." );
442 EM_log( CK_LOG_FINE
, "trying %d input %d output...",
443 m_num_channels_in
, m_num_channels_out
);
445 m_rtaudio
->openStream(
446 m_dac_n
, m_num_channels_out
, m_adc_n
, m_num_channels_in
,
447 CK_RTAUDIO_FORMAT
, sampling_rate
,
448 &bufsize
, num_buffers
);
453 EM_log( CK_LOG_INFO
, "initializing callback..." );
456 if( block
) m_rtaudio
->setStreamCallback( &cb
, vm_ref
);
457 else m_rtaudio
->setStreamCallback( &cb2
, vm_ref
);
461 m_rtaudio
->setStreamCallback( (RtAudioCallback
)callback
, data
);
464 } catch( RtError err
) {
466 EM_log( CK_LOG_INFO
, "exception caught: '%s'...", err
.getMessageString() );
467 EM_log( CK_LOG_INFO
, "trying %d input %d output...", 0, m_num_channels_out
);
469 bufsize
= buffer_size
;
471 m_rtaudio
->openStream(
472 m_dac_n
, m_num_channels_out
, 0, 0,
473 RTAUDIO_FLOAT32
, sampling_rate
,
474 &bufsize
, num_buffers
);
479 EM_log( CK_LOG_INFO
, "initializing callback (again)..." );
482 if( block
) m_rtaudio
->setStreamCallback( &cb
, vm_ref
);
483 else m_rtaudio
->setStreamCallback( &cb2
, vm_ref
);
487 m_rtaudio
->setStreamCallback( (RtAudioCallback
)callback
, data
);
490 } catch( RtError err
) {
491 EM_error2( 0, "%s", err
.getMessageString() );
492 SAFE_DELETE( m_rtaudio
);
493 return m_init
= FALSE
;
498 if( bufsize
!= (int)m_buffer_size
)
500 EM_log( CK_LOG_SEVERE
, "new buffer size: %d -> %i", m_buffer_size
, bufsize
);
501 m_buffer_size
= bufsize
;
507 #endif // __DISABLE_RTAUDIO__
509 #if defined(__CHIP_MODE__)
510 if( !SMALL::init( sampling_rate
, buffer_size
, 2 ) )
512 EM_error2( 0, "%s", "(chuck)error: unable to initialize SMALL..." );
513 return m_init
= FALSE
;
515 #endif // __CHIP_MODE__
519 num_channels
= num_dac_channels
> num_adc_channels
?
520 num_dac_channels
: num_adc_channels
;
522 EM_log( CK_LOG_SEVERE
, "allocating buffers for %d x %d samples...",
523 m_buffer_size
, num_channels
);
525 m_buffer_in
= new SAMPLE
[m_buffer_size
* num_channels
];
526 m_buffer_out
= new SAMPLE
[m_buffer_size
* num_channels
];
527 memset( m_buffer_in
, 0, m_buffer_size
* sizeof(SAMPLE
) * num_channels
);
528 memset( m_buffer_out
, 0, m_buffer_size
* sizeof(SAMPLE
) * num_channels
);
536 return m_init
= TRUE
;
542 //-----------------------------------------------------------------------------
545 //-----------------------------------------------------------------------------
546 int Digitalio::cb( char * buffer
, int buffer_size
, void * user_data
)
548 DWORD__ len
= buffer_size
* sizeof(SAMPLE
) * m_num_channels_out
;
552 // copy input to local buffer
553 if( m_num_channels_in
)
555 memcpy( m_buffer_in
, buffer
, len
);
557 if( m_extern_in
) memcpy( m_extern_in
, buffer
, len
);
561 // out is ready early
562 if( m_go
< start
&& m_go
> 1 && m_out_ready
) m_go
= start
;
563 // copy output into local buffer
566 while( !m_out_ready
&& n
-- ) usleep( 250 );
567 if( m_out_ready
&& g_do_watchdog
)
568 g_watchdog_time
= get_current_time( TRUE
);
569 // copy local buffer to be rendered
570 if( m_out_ready
&& !m_end
) memcpy( buffer
, m_buffer_out
, len
);
571 // set all elements of local buffer to silence
572 else memset( buffer
, 0, len
);
574 else // initial condition
577 if( !m_go
&& Chuck_VM::our_priority
!= 0x7fffffff )
578 Chuck_VM::set_priority( Chuck_VM::our_priority
, NULL
);
580 // signal( SIGINT, signal_int );
583 if( g_do_watchdog
) g_watchdog_time
= get_current_time( TRUE
);
585 memset( buffer
, 0, len
);
593 n
= 8; while( !m_out_ready
&& n
-- ) usleep( 250 );
594 len
/= sizeof(SAMPLE
); DWORD__ i
= 0;
595 SAMPLE
* s
= (SAMPLE
*)buffer
;
596 while( i
< len
) *s
++ *= (SAMPLE
)i
++/len
;
601 if( m_extern_out
) memcpy( m_extern_out
, buffer
, len
);
603 // set pointer to the beginning - if not ready, then too late anyway
604 //*m_write_ptr = (SAMPLE *)m_buffer_out;
605 //*m_read_ptr = (SAMPLE *)m_buffer_in;
614 //-----------------------------------------------------------------------------
617 //-----------------------------------------------------------------------------
618 int Digitalio::cb2( char * buffer
, int buffer_size
, void * user_data
)
620 DWORD__ len
= buffer_size
* sizeof(SAMPLE
) * m_num_channels_out
;
621 Chuck_VM
* vm_ref
= (Chuck_VM
*)user_data
;
624 if( !m_go
&& Chuck_VM::our_priority
!= 0x7fffffff )
626 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
627 g_tid_synthesis
= pthread_self();
629 // must duplicate for handle to be usable by other threads
630 g_tid_synthesis
= NULL
;
638 DUPLICATE_SAME_ACCESS
641 // TODO: close the duplicate handle?
643 Chuck_VM::set_priority( Chuck_VM::our_priority
, NULL
);
644 memset( buffer
, 0, len
);
651 g_watchdog_time
= get_current_time( TRUE
);
656 // let it go the first time
660 // copy input to local buffer
661 if( m_num_channels_in
)
663 memcpy( m_buffer_in
, buffer
, len
);
665 if( m_extern_in
) memcpy( m_extern_in
, buffer
, len
);
672 if( g_do_watchdog
) g_watchdog_time
= get_current_time( TRUE
);
673 // get samples from output
674 vm_ref
->run( buffer_size
);
676 if( m_xrun
) m_xrun
--;
684 // copy local buffer to be rendered
685 if( !m_end
) memcpy( buffer
, m_buffer_out
, len
);
686 // set all elements of local buffer to silence
687 else memset( buffer
, 0, len
);
690 if( m_extern_out
) memcpy( m_extern_out
, buffer
, len
);
699 #ifdef __SMALL_MODE__
700 //-----------------------------------------------------------------------------
703 //-----------------------------------------------------------------------------
704 void small_cb( Float32
* buffer
, UInt32 numFrames
, void * userData
)
706 Digitalio::cb2( (char *)buffer
, numFrames
, userData
);
708 #endif __SMALL_MODE__
713 //-----------------------------------------------------------------------------
716 //-----------------------------------------------------------------------------
717 BOOL__
Digitalio::start( )
719 #ifndef __DISABLE_RTAUDIO__
721 m_rtaudio
->startStream();
723 } catch( RtError err
){ return FALSE
; }
724 #endif // __DISABLE_RTAUDIO__
726 #if defined(__CHIP_MODE__)
728 m_start
= SMALL::start( small_cb
, g_vm
);
729 #endif // __CHIP_MODE__
737 //-----------------------------------------------------------------------------
740 //-----------------------------------------------------------------------------
741 BOOL__
Digitalio::stop( )
743 #ifndef __DISABLE_RTAUDIO__
745 m_rtaudio
->stopStream();
747 } catch( RtError err
){ return FALSE
; }
748 #endif // __DISABLE_RTAUDIO__
750 #if defined(__CHIP_MODE__)
762 //-----------------------------------------------------------------------------
765 //-----------------------------------------------------------------------------
766 BOOL__
Digitalio::tick( )
768 #ifndef __DISABLE_RTAUDIO__
771 if( ++m_tick_count
>= m_start
)
773 m_rtaudio
->tickStream();
780 } catch( RtError err
){ return FALSE
; }
781 #endif // __DISABLE_RTAUDIO__
789 //-----------------------------------------------------------------------------
792 //-----------------------------------------------------------------------------
793 void Digitalio::shutdown()
795 if( !m_init
) return;
797 #ifndef __DISABLE_RTAUDIO__
800 if( m_use_cb
) m_rtaudio
->cancelStreamCallback();
801 m_rtaudio
->stopStream();
804 m_rtaudio
->closeStream();
805 SAFE_DELETE( m_rtaudio
);
806 #endif // __DISABLE_RTAUDIO__
818 //-----------------------------------------------------------------------------
819 // name: DigitalOut()
821 //-----------------------------------------------------------------------------
822 DigitalOut::DigitalOut()
824 m_data_ptr_out
= NULL
;
825 m_data_max_out
= NULL
;
831 //-----------------------------------------------------------------------------
832 // name: ~DigitalOut()
834 //-----------------------------------------------------------------------------
835 DigitalOut::~DigitalOut()
843 //-----------------------------------------------------------------------------
844 // name: initialize()
845 // desc: initialize audio out
846 //-----------------------------------------------------------------------------
847 BOOL__
DigitalOut::initialize( )
849 #ifndef __DISABLE_RTAUDIO__
850 // set pointer to beginning of local buffer
851 m_data_ptr_out
= Digitalio::m_use_cb
? Digitalio::m_buffer_out
852 : (SAMPLE
*)Digitalio::audio()->getStreamBuffer();
855 assert( Digitalio::m_use_cb
);
856 m_data_ptr_out
= Digitalio::m_buffer_out
;
857 #endif // __DISABLE_RTAUDIO__
858 // calculate the end of the buffer
859 m_data_max_out
= m_data_ptr_out
+
860 Digitalio::buffer_size() * Digitalio::num_channels_out();
861 // set the writer pointer to our write pointer
862 Digitalio::m_write_ptr
= &m_data_ptr_out
;
870 //-----------------------------------------------------------------------------
873 //-----------------------------------------------------------------------------
874 BOOL__
DigitalOut::start()
877 return ( Digitalio::start() != 0 );
883 //-----------------------------------------------------------------------------
886 //-----------------------------------------------------------------------------
887 BOOL__
DigitalOut::stop()
898 //-----------------------------------------------------------------------------
901 //-----------------------------------------------------------------------------
902 void DigitalOut::cleanup()
909 //-----------------------------------------------------------------------------
912 //-----------------------------------------------------------------------------
913 BOOL__
DigitalOut::tick_out( SAMPLE sample
)
915 if( !prepare_tick_out() )
918 *m_data_ptr_out
++ = sample
;
926 //-----------------------------------------------------------------------------
929 //-----------------------------------------------------------------------------
930 BOOL__
DigitalOut::tick_out( SAMPLE sample_l
, SAMPLE sample_r
)
932 if( !prepare_tick_out() )
935 *m_data_ptr_out
++ = sample_l
;
936 *m_data_ptr_out
++ = sample_r
;
944 //-----------------------------------------------------------------------------
946 // desc: all channels
947 //-----------------------------------------------------------------------------
948 BOOL__
DigitalOut::tick_out( const SAMPLE
* samples
, DWORD__ n
)
950 if( !prepare_tick_out() )
953 if( !n
) n
= Digitalio::m_num_channels_out
;
955 *m_data_ptr_out
++ = *samples
++;
963 //-----------------------------------------------------------------------------
964 // name: prepare_tick_out()
966 //-----------------------------------------------------------------------------
967 inline BOOL__
DigitalOut::prepare_tick_out()
969 if( m_data_ptr_out
>= m_data_max_out
)
980 //-----------------------------------------------------------------------------
983 //-----------------------------------------------------------------------------
984 DWORD__
DigitalOut::render()
986 //if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE;
988 if( Digitalio::m_block
)
991 Digitalio::m_out_ready
= TRUE
;
993 while( Digitalio::m_out_ready
)
997 // set pointer to the beginning - if not ready, then too late anyway
998 *Digitalio::m_write_ptr
= (SAMPLE
*)Digitalio::m_buffer_out
;
1006 //-----------------------------------------------------------------------------
1007 // name: DigitalIn()
1009 //-----------------------------------------------------------------------------
1010 DigitalIn::DigitalIn()
1012 m_data_ptr_in
= NULL
;
1013 m_data_max_in
= NULL
;
1019 //-----------------------------------------------------------------------------
1020 // name: ~DigitalIn()
1022 //-----------------------------------------------------------------------------
1023 DigitalIn::~DigitalIn()
1031 //-----------------------------------------------------------------------------
1032 // name: initialize()
1033 // desc: initialize audio in
1034 //-----------------------------------------------------------------------------
1035 BOOL__
DigitalIn::initialize( )
1037 m_data
= new SAMPLE
[Digitalio::buffer_size() * Digitalio::num_channels_in()];
1038 memset( m_data
, 0, Digitalio::buffer_size() * Digitalio::num_channels_in() * sizeof(SAMPLE
) );
1039 #ifndef __DISABLE_RTAUDIO__
1040 // set the buffer to the beginning of the local buffer
1041 m_data_ptr_in
= Digitalio::m_use_cb
? m_data
1042 : (SAMPLE
*)Digitalio::audio()->getStreamBuffer();
1044 // set the buffer pointer
1045 assert( Digitalio::m_use_cb
);
1046 m_data_ptr_in
= m_data
;
1047 #endif // __DISABLE_RTAUDIO__
1048 // calculate past buffer
1049 m_data_max_in
= m_data_ptr_in
+
1050 Digitalio::buffer_size() * Digitalio::num_channels_in();
1051 // set the read pointer to the local pointer
1052 Digitalio::m_read_ptr
= &m_data_ptr_in
;
1054 m_data_ptr_in
= m_data_max_in
;
1062 //-----------------------------------------------------------------------------
1065 //-----------------------------------------------------------------------------
1066 BOOL__
DigitalIn::start()
1068 return ( Digitalio::start() != 0 );
1074 //-----------------------------------------------------------------------------
1075 // name: capture_stop()
1077 //-----------------------------------------------------------------------------
1078 BOOL__
DigitalIn::stop()
1087 //-----------------------------------------------------------------------------
1090 //-----------------------------------------------------------------------------
1091 void DigitalIn::cleanup()
1098 //-----------------------------------------------------------------------------
1101 //-----------------------------------------------------------------------------
1102 BOOL__
DigitalIn::tick_in( SAMPLE
* s
)
1104 if( !prepare_tick_in() )
1106 *s
= *m_data_ptr_in
++;
1114 //-----------------------------------------------------------------------------
1117 //-----------------------------------------------------------------------------
1118 BOOL__
DigitalIn::tick_in( SAMPLE
* l
, SAMPLE
* r
)
1120 if( !prepare_tick_in() )
1123 *l
= *m_data_ptr_in
++;
1124 *r
= *m_data_ptr_in
++;
1132 //-----------------------------------------------------------------------------
1135 //-----------------------------------------------------------------------------
1136 BOOL__
DigitalIn::tick_in( SAMPLE
* sample
, DWORD__ n
)
1138 if( !prepare_tick_in() )
1141 if( !n
) n
= Digitalio::m_num_channels_in
;
1143 *sample
++ = *m_data_ptr_in
++;
1151 //-----------------------------------------------------------------------------
1152 // name: prepare_tick_in()
1153 // desc: data ptr ok
1154 //-----------------------------------------------------------------------------
1155 inline BOOL__
DigitalIn::prepare_tick_in()
1157 if( m_data_ptr_in
>= m_data_max_in
)
1168 //-----------------------------------------------------------------------------
1169 // name: cb_capture()
1171 //-----------------------------------------------------------------------------
1172 DWORD__
DigitalIn::capture( )
1174 // if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE;
1176 if( Digitalio::m_block
)
1179 while( !Digitalio::m_in_ready
&& n
-- )
1184 memcpy( m_data
, Digitalio::m_buffer_in
, Digitalio::buffer_size() *
1185 Digitalio::num_channels_in() * sizeof(SAMPLE
) );
1186 Digitalio::m_in_ready
= FALSE
;
1187 // set pointer to the beginning - if not ready, then too late anyway
1188 *Digitalio::m_read_ptr
= (SAMPLE
*)m_data
;
1196 //-----------------------------------------------------------------------------
1197 // name: AudioBufferX()
1199 //-----------------------------------------------------------------------------
1200 AudioBufferX::AudioBufferX( DWORD__ size
)
1203 this->initialize( size
);
1207 m_data
= m_ptr_curr
= m_ptr_end
= NULL
;
1214 //-----------------------------------------------------------------------------
1215 // name: initialize()
1217 //-----------------------------------------------------------------------------
1218 BOOL__
AudioBufferX::initialize( DWORD__ size
)
1221 m_data
= (SAMPLE
*)malloc( size
* sizeof(SAMPLE
) );
1227 memset( m_data
, 0, size
* sizeof(SAMPLE
) );
1230 m_ptr_curr
= m_data
;
1231 m_ptr_end
= m_data
+ size
;
1239 //-----------------------------------------------------------------------------
1242 //-----------------------------------------------------------------------------
1243 void AudioBufferX::cleanup()
1252 m_ptr_curr
= m_ptr_end
= NULL
;
1258 //-----------------------------------------------------------------------------
1261 //-----------------------------------------------------------------------------
1262 DWORD__
AudioBufferX::size()
1270 //-----------------------------------------------------------------------------
1273 //-----------------------------------------------------------------------------
1274 SAMPLE
* AudioBufferX::data()
1282 //-----------------------------------------------------------------------------
1283 // name: AudioBufferIn()
1285 //-----------------------------------------------------------------------------
1286 AudioBufferIn::AudioBufferIn( DWORD__ size
)
1287 : AudioBufferX( size
)
1293 //-----------------------------------------------------------------------------
1294 // name: ~AudioBufferIn()
1296 //-----------------------------------------------------------------------------
1297 AudioBufferIn::~AudioBufferIn()
1305 //-----------------------------------------------------------------------------
1308 //-----------------------------------------------------------------------------
1309 BOOL__
AudioBufferIn::reset()
1311 m_ptr_curr
= m_data
;
1313 return TickIn::reset();
1319 //-----------------------------------------------------------------------------
1322 //-----------------------------------------------------------------------------
1323 BOOL__
AudioBufferIn::tick_in( SAMPLE
* s
)
1336 //-----------------------------------------------------------------------------
1339 //-----------------------------------------------------------------------------
1340 BOOL__
AudioBufferIn::tick_in( SAMPLE
* l
, SAMPLE
* r
)
1342 if( !m_data
|| m_ptr_curr
+ 2 >= m_ptr_end
)
1354 //-----------------------------------------------------------------------------
1357 //-----------------------------------------------------------------------------
1358 BOOL__
AudioBufferIn::tick_in( SAMPLE
* in
, DWORD__ n
)
1360 if( !m_data
|| m_ptr_curr
+ n
>= m_ptr_end
)
1364 *in
++ = *m_ptr_curr
++;
1372 //-----------------------------------------------------------------------------
1373 // name: AudioBufferOut()
1375 //-----------------------------------------------------------------------------
1376 AudioBufferOut::AudioBufferOut( DWORD__ size
)
1377 : AudioBufferX( size
)
1383 //-----------------------------------------------------------------------------
1384 // name: ~AudioBufferOut()
1386 //-----------------------------------------------------------------------------
1387 AudioBufferOut::~AudioBufferOut()
1395 //-----------------------------------------------------------------------------
1398 //-----------------------------------------------------------------------------
1399 BOOL__
AudioBufferOut::reset()
1401 m_ptr_curr
= m_data
;
1403 return TickOut::reset();
1409 //-----------------------------------------------------------------------------
1412 //-----------------------------------------------------------------------------
1413 BOOL__
AudioBufferOut::tick_out( SAMPLE s
)
1426 //-----------------------------------------------------------------------------
1429 //-----------------------------------------------------------------------------
1430 BOOL__
AudioBufferOut::tick_out( SAMPLE l
, SAMPLE r
)
1432 if( !m_data
|| m_ptr_curr
+ 2 >= m_ptr_end
)
1444 //-----------------------------------------------------------------------------
1447 //-----------------------------------------------------------------------------
1448 BOOL__
AudioBufferOut::tick_out( const SAMPLE
* out
, DWORD__ n
)
1450 if( !m_data
|| m_ptr_curr
+ n
>= m_ptr_end
)
1454 *m_ptr_curr
++ = *out
++;