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"
36 #if defined(__WINDOWS_DS__) && !defined(__WINDOWS_PTHREAD__)
46 BOOL__
Digitalio::m_init
= FALSE
;
47 DWORD__
Digitalio::m_start
= 0;
48 DWORD__
Digitalio::m_tick_count
= 0;
49 DWORD__
Digitalio::m_num_channels_out
= NUM_CHANNELS_DEFAULT
;
50 DWORD__
Digitalio::m_num_channels_in
= NUM_CHANNELS_DEFAULT
;
51 DWORD__
Digitalio::m_sampling_rate
= SAMPLING_RATE_DEFAULT
;
52 DWORD__
Digitalio::m_bps
= BITS_PER_SAMPLE_DEFAULT
;
53 DWORD__
Digitalio::m_buffer_size
= BUFFER_SIZE_DEFAULT
;
54 DWORD__
Digitalio::m_num_buffers
= NUM_BUFFERS_DEFAULT
;
55 RtAudio
* Digitalio::m_rtaudio
= NULL
;
56 SAMPLE
* Digitalio::m_buffer_out
= NULL
;
57 SAMPLE
* Digitalio::m_buffer_in
= NULL
;
58 SAMPLE
** Digitalio::m_write_ptr
= NULL
;
59 SAMPLE
** Digitalio::m_read_ptr
= NULL
;
60 SAMPLE
* Digitalio::m_extern_in
= NULL
;
61 SAMPLE
* Digitalio::m_extern_out
= NULL
;
62 BOOL__
Digitalio::m_out_ready
= FALSE
;
63 BOOL__
Digitalio::m_in_ready
= FALSE
;
64 BOOL__
Digitalio::m_use_cb
= USE_CB_DEFAULT
;
65 DWORD__
Digitalio::m_go
= 0;
66 DWORD__
Digitalio::m_dac_n
= 0;
67 DWORD__
Digitalio::m_adc_n
= 0;
68 DWORD__
Digitalio::m_end
= 0;
73 //-----------------------------------------------------------------------------
76 //-----------------------------------------------------------------------------
77 BOOL__
Digitalio::initialize( DWORD__ num_channels
, DWORD__ sampling_rate
,
78 DWORD__ bps
, DWORD__ buffer_size
,
84 m_num_channels_out
= num_channels
;
85 m_num_channels_in
= num_channels
;
86 m_sampling_rate
= sampling_rate
;
88 m_buffer_size
= buffer_size
;
89 m_num_buffers
= num_buffers
;
96 try { m_rtaudio
= new RtAudio( ); }
99 // problem finding audio devices, most likely
100 EM_error2( 0, "%s", err
.getMessageString() );
101 return m_init
= FALSE
;
106 m_rtaudio
->openStream(
107 m_dac_n
, m_num_channels_out
, m_adc_n
, m_num_channels_in
,
108 RTAUDIO_FLOAT32
, sampling_rate
,
109 (int *)&m_buffer_size
, num_buffers
);
111 m_rtaudio
->setStreamCallback( &cb
, NULL
);
112 } catch( RtError err
) {
114 m_buffer_size
= buffer_size
;
116 m_rtaudio
->openStream(
117 m_dac_n
, m_num_channels_out
, 0, 0,
118 RTAUDIO_FLOAT32
, sampling_rate
,
119 (int *)&m_buffer_size
, num_buffers
);
121 m_rtaudio
->setStreamCallback( &cb
, NULL
);
122 } catch( RtError err
) {
123 EM_error2( 0, "%s", err
.getMessageString() );
124 SAFE_DELETE( m_rtaudio
);
125 return m_init
= FALSE
;
131 m_buffer_in
= new SAMPLE
[m_buffer_size
* num_channels
];
132 m_buffer_out
= new SAMPLE
[m_buffer_size
* num_channels
];
133 memset( m_buffer_in
, 0, m_buffer_size
* sizeof(SAMPLE
) * num_channels
);
134 memset( m_buffer_out
, 0, m_buffer_size
* sizeof(SAMPLE
) * num_channels
);
142 return m_init
= TRUE
;
148 //-----------------------------------------------------------------------------
151 //-----------------------------------------------------------------------------
152 int Digitalio::cb( char * buffer
, int buffer_size
, void * user_data
)
154 DWORD__ len
= buffer_size
* sizeof(SAMPLE
) * m_num_channels_out
;
158 // copy input to local buffer
159 if( m_num_channels_in
)
161 memcpy( m_buffer_in
, buffer
, len
);
163 if( m_extern_in
) memcpy( m_extern_in
, buffer
, len
);
167 // out is ready early
168 if( m_go
< start
&& m_go
> 1 && m_out_ready
) m_go
= start
;
169 // copy output into local buffer
172 while( !m_out_ready
&& n
-- ) usleep( 250 );
173 // copy local buffer to be rendered
174 if( m_out_ready
&& !m_end
) memcpy( buffer
, m_buffer_out
, len
);
175 // set all elements of local buffer to silence
176 else memset( buffer
, 0, len
);
178 else // initial condition
180 //#ifndef __WINDOWS_DS__
181 if( !m_go
&& Chuck_VM::our_priority
!= 0x7fffffff )
182 Chuck_VM::set_priority( Chuck_VM::our_priority
, NULL
);
184 memset( buffer
, 0, len
);
192 n
= 8; while( !m_out_ready
&& n
-- ) usleep( 250 );
193 len
/= sizeof(SAMPLE
); DWORD__ i
= 0;
194 SAMPLE
* s
= (SAMPLE
*)buffer
;
195 while( i
< len
) *s
++ *= (SAMPLE
)i
++/len
;
200 if( m_extern_out
) memcpy( m_extern_out
, buffer
, len
);
202 // set pointer to the beginning - if not ready, then too late anyway
203 //*m_write_ptr = (SAMPLE *)m_buffer_out;
204 //*m_read_ptr = (SAMPLE *)m_buffer_in;
213 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
217 BOOL__
Digitalio::start( )
220 m_rtaudio
->startStream();
222 } catch( RtError err
){ return FALSE
; }
230 //-----------------------------------------------------------------------------
233 //-----------------------------------------------------------------------------
234 BOOL__
Digitalio::stop( )
237 m_rtaudio
->stopStream();
239 } catch( RtError err
){ return FALSE
; }
247 //-----------------------------------------------------------------------------
250 //-----------------------------------------------------------------------------
251 BOOL__
Digitalio::tick( )
255 if( ++m_tick_count
>= m_start
)
257 m_rtaudio
->tickStream();
264 } catch( RtError err
){ return FALSE
; }
270 //-----------------------------------------------------------------------------
273 //-----------------------------------------------------------------------------
274 void Digitalio::shutdown()
276 if( !m_init
) return;
277 if( m_start
) m_rtaudio
->stopStream();
279 m_rtaudio
->closeStream();
280 SAFE_DELETE( m_rtaudio
);
288 //-----------------------------------------------------------------------------
289 // name: DigitalOut()
291 //-----------------------------------------------------------------------------
292 DigitalOut::DigitalOut()
294 m_data_ptr_out
= NULL
;
295 m_data_max_out
= NULL
;
301 //-----------------------------------------------------------------------------
302 // name: ~DigitalOut()
304 //-----------------------------------------------------------------------------
305 DigitalOut::~DigitalOut()
313 //-----------------------------------------------------------------------------
314 // name: initialize()
315 // desc: initialize audio out
316 //-----------------------------------------------------------------------------
317 BOOL__
DigitalOut::initialize( )
319 // set pointer to beginning of local buffer
320 m_data_ptr_out
= Digitalio::m_use_cb
? Digitalio::m_buffer_out
321 : (SAMPLE
*)Digitalio::audio()->getStreamBuffer();
322 // calculate the end of the buffer
323 m_data_max_out
= m_data_ptr_out
+
324 Digitalio::buffer_size() * Digitalio::num_channels_out();
325 // set the writer pointer to our write pointer
326 Digitalio::m_write_ptr
= &m_data_ptr_out
;
334 //-----------------------------------------------------------------------------
337 //-----------------------------------------------------------------------------
338 BOOL__
DigitalOut::start()
341 return ( Digitalio::start() != 0 );
347 //-----------------------------------------------------------------------------
350 //-----------------------------------------------------------------------------
351 BOOL__
DigitalOut::stop()
362 //-----------------------------------------------------------------------------
365 //-----------------------------------------------------------------------------
366 void DigitalOut::cleanup()
373 //-----------------------------------------------------------------------------
376 //-----------------------------------------------------------------------------
377 BOOL__
DigitalOut::tick_out( SAMPLE sample
)
379 if( !prepare_tick_out() )
382 *m_data_ptr_out
++ = sample
;
390 //-----------------------------------------------------------------------------
393 //-----------------------------------------------------------------------------
394 BOOL__
DigitalOut::tick_out( SAMPLE sample_l
, SAMPLE sample_r
)
396 if( !prepare_tick_out() )
399 *m_data_ptr_out
++ = sample_l
;
400 *m_data_ptr_out
++ = sample_r
;
408 //-----------------------------------------------------------------------------
410 // desc: all channels
411 //-----------------------------------------------------------------------------
412 BOOL__
DigitalOut::tick_out( const SAMPLE
* samples
, DWORD__ n
)
414 if( !prepare_tick_out() )
417 if( !n
) n
= Digitalio::m_num_channels_out
;
419 *m_data_ptr_out
++ = *samples
++;
427 //-----------------------------------------------------------------------------
428 // name: prepare_tick_out()
430 //-----------------------------------------------------------------------------
431 inline BOOL__
DigitalOut::prepare_tick_out()
433 if( m_data_ptr_out
>= m_data_max_out
)
444 //-----------------------------------------------------------------------------
447 //-----------------------------------------------------------------------------
448 DWORD__
DigitalOut::render()
450 //if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE;
453 Digitalio::m_out_ready
= TRUE
;
455 while( Digitalio::m_out_ready
)
457 // set pointer to the beginning - if not ready, then too late anyway
458 *Digitalio::m_write_ptr
= (SAMPLE
*)Digitalio::m_buffer_out
;
466 //-----------------------------------------------------------------------------
469 //-----------------------------------------------------------------------------
470 DigitalIn::DigitalIn()
472 m_data_ptr_in
= NULL
;
473 m_data_max_in
= NULL
;
479 //-----------------------------------------------------------------------------
480 // name: ~DigitalIn()
482 //-----------------------------------------------------------------------------
483 DigitalIn::~DigitalIn()
491 //-----------------------------------------------------------------------------
492 // name: initialize()
493 // desc: initialize audio in
494 //-----------------------------------------------------------------------------
495 BOOL__
DigitalIn::initialize( )
497 m_data
= new SAMPLE
[Digitalio::buffer_size() * Digitalio::num_channels_in()];
498 // set the buffer to the beginning of the local buffer
499 m_data_ptr_in
= Digitalio::m_use_cb
? m_data
500 : (SAMPLE
*)Digitalio::audio()->getStreamBuffer();
501 // calculate past buffer
502 m_data_max_in
= m_data_ptr_in
+
503 Digitalio::buffer_size() * Digitalio::num_channels_in();
504 // set the read pointer to the local pointer
505 Digitalio::m_read_ptr
= &m_data_ptr_in
;
513 //-----------------------------------------------------------------------------
516 //-----------------------------------------------------------------------------
517 BOOL__
DigitalIn::start()
519 return ( Digitalio::start() != 0 );
525 //-----------------------------------------------------------------------------
526 // name: capture_stop()
528 //-----------------------------------------------------------------------------
529 BOOL__
DigitalIn::stop()
538 //-----------------------------------------------------------------------------
541 //-----------------------------------------------------------------------------
542 void DigitalIn::cleanup()
549 //-----------------------------------------------------------------------------
552 //-----------------------------------------------------------------------------
553 BOOL__
DigitalIn::tick_in( SAMPLE
* s
)
555 if( !prepare_tick_in() )
558 *s
= *m_data_ptr_in
++;
566 //-----------------------------------------------------------------------------
569 //-----------------------------------------------------------------------------
570 BOOL__
DigitalIn::tick_in( SAMPLE
* l
, SAMPLE
* r
)
572 if( !prepare_tick_in() )
575 *l
= *m_data_ptr_in
++;
576 *r
= *m_data_ptr_in
++;
584 //-----------------------------------------------------------------------------
587 //-----------------------------------------------------------------------------
588 BOOL__
DigitalIn::tick_in( SAMPLE
* sample
, DWORD__ n
)
590 if( !prepare_tick_in() )
593 if( !n
) n
= Digitalio::m_num_channels_in
;
595 *sample
++ = *m_data_ptr_in
++;
603 //-----------------------------------------------------------------------------
604 // name: prepare_tick_in()
606 //-----------------------------------------------------------------------------
607 inline BOOL__
DigitalIn::prepare_tick_in()
609 if( m_data_ptr_in
>= m_data_max_in
)
620 //-----------------------------------------------------------------------------
621 // name: cb_capture()
623 //-----------------------------------------------------------------------------
624 DWORD__
DigitalIn::capture( )
626 // if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE;
629 while( !Digitalio::m_in_ready
&& n
-- )
633 memcpy( m_data
, Digitalio::m_buffer_in
, Digitalio::buffer_size() *
634 Digitalio::num_channels_in() * sizeof(SAMPLE
) );
635 Digitalio::m_in_ready
= FALSE
;
636 // set pointer to the beginning - if not ready, then too late anyway
637 *Digitalio::m_read_ptr
= (SAMPLE
*)m_data
;
645 //-----------------------------------------------------------------------------
646 // name: AudioBufferX()
648 //-----------------------------------------------------------------------------
649 AudioBufferX::AudioBufferX( DWORD__ size
)
652 this->initialize( size
);
656 m_data
= m_ptr_curr
= m_ptr_end
= NULL
;
663 //-----------------------------------------------------------------------------
664 // name: initialize()
666 //-----------------------------------------------------------------------------
667 BOOL__
AudioBufferX::initialize( DWORD__ size
)
670 m_data
= (SAMPLE
*)malloc( size
* sizeof(SAMPLE
) );
676 memset( m_data
, 0, size
* sizeof(SAMPLE
) );
680 m_ptr_end
= m_data
+ size
;
688 //-----------------------------------------------------------------------------
691 //-----------------------------------------------------------------------------
692 void AudioBufferX::cleanup()
701 m_ptr_curr
= m_ptr_end
= NULL
;
707 //-----------------------------------------------------------------------------
710 //-----------------------------------------------------------------------------
711 DWORD__
AudioBufferX::size()
719 //-----------------------------------------------------------------------------
722 //-----------------------------------------------------------------------------
723 SAMPLE
* AudioBufferX::data()
731 //-----------------------------------------------------------------------------
732 // name: AudioBufferIn()
734 //-----------------------------------------------------------------------------
735 AudioBufferIn::AudioBufferIn( DWORD__ size
)
736 : AudioBufferX( size
)
742 //-----------------------------------------------------------------------------
743 // name: ~AudioBufferIn()
745 //-----------------------------------------------------------------------------
746 AudioBufferIn::~AudioBufferIn()
754 //-----------------------------------------------------------------------------
757 //-----------------------------------------------------------------------------
758 BOOL__
AudioBufferIn::reset()
762 return TickIn::reset();
768 //-----------------------------------------------------------------------------
771 //-----------------------------------------------------------------------------
772 BOOL__
AudioBufferIn::tick_in( SAMPLE
* s
)
785 //-----------------------------------------------------------------------------
788 //-----------------------------------------------------------------------------
789 BOOL__
AudioBufferIn::tick_in( SAMPLE
* l
, SAMPLE
* r
)
791 if( !m_data
|| m_ptr_curr
+ 2 >= m_ptr_end
)
803 //-----------------------------------------------------------------------------
806 //-----------------------------------------------------------------------------
807 BOOL__
AudioBufferIn::tick_in( SAMPLE
* in
, DWORD__ n
)
809 if( !m_data
|| m_ptr_curr
+ n
>= m_ptr_end
)
813 *in
++ = *m_ptr_curr
++;
821 //-----------------------------------------------------------------------------
822 // name: AudioBufferOut()
824 //-----------------------------------------------------------------------------
825 AudioBufferOut::AudioBufferOut( DWORD__ size
)
826 : AudioBufferX( size
)
832 //-----------------------------------------------------------------------------
833 // name: ~AudioBufferOut()
835 //-----------------------------------------------------------------------------
836 AudioBufferOut::~AudioBufferOut()
844 //-----------------------------------------------------------------------------
847 //-----------------------------------------------------------------------------
848 BOOL__
AudioBufferOut::reset()
852 return TickOut::reset();
858 //-----------------------------------------------------------------------------
861 //-----------------------------------------------------------------------------
862 BOOL__
AudioBufferOut::tick_out( SAMPLE s
)
875 //-----------------------------------------------------------------------------
878 //-----------------------------------------------------------------------------
879 BOOL__
AudioBufferOut::tick_out( SAMPLE l
, SAMPLE r
)
881 if( !m_data
|| m_ptr_curr
+ 2 >= m_ptr_end
)
893 //-----------------------------------------------------------------------------
896 //-----------------------------------------------------------------------------
897 BOOL__
AudioBufferOut::tick_out( const SAMPLE
* out
, DWORD__ n
)
899 if( !m_data
|| m_ptr_curr
+ n
>= m_ptr_end
)
903 *m_ptr_curr
++ = *out
++;