From 29d139d7aaab3bc8e89ec58d7fb70dbc3db1929e Mon Sep 17 00:00:00 2001 From: gw-chuck Date: Sun, 24 Aug 2008 00:33:29 +0000 Subject: [PATCH] *** empty log message *** --- v2/chuck_instr.cpp | 9 ++- v2/chuck_main.cpp | 8 ++- v2/chuck_ugen.cpp | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++ v2/chuck_ugen.h | 7 +++ v2/chuck_vm.cpp | 117 +++++++++++++++++++++++++++++++++++++-- v2/chuck_vm.h | 9 ++- 6 files changed, 300 insertions(+), 10 deletions(-) diff --git a/v2/chuck_instr.cpp b/v2/chuck_instr.cpp index d4e0c4ab..eb33101d 100755 --- a/v2/chuck_instr.cpp +++ b/v2/chuck_instr.cpp @@ -41,6 +41,7 @@ #include "chuck_bbq.h" #include "chuck_dl.h" #include "chuck_errmsg.h" +#include "chuck_globals.h" #include "util_string.h" @@ -2707,6 +2708,8 @@ Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Sh { Chuck_Object * object = NULL; Chuck_UAna * uana = NULL; + // TODO: this is a hack! + Chuck_VM * vm_ref = shred ? shred->vm_ref : g_vm; // sanity assert( type != NULL ); @@ -2731,10 +2734,12 @@ Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Sh { // uana object = ugen = uana = new Chuck_UAna; + ugen->alloc_v( vm_ref->shreduler()->m_max_block_size ); } else { object = ugen = new Chuck_UGen; + ugen->alloc_v( vm_ref->shreduler()->m_max_block_size ); } if( shred ) @@ -4338,7 +4343,7 @@ void Chuck_Instr_Array_Append::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // reg stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; - t_CKINT i = 0; + // t_CKINT i = 0; t_CKUINT val = 0; t_CKFLOAT fval = 0; t_CKCOMPLEX cval; @@ -4596,7 +4601,7 @@ void Chuck_Instr_Dot_Cmp_First::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) pop_( sp, 1 ); // push the addr on if( m_emit_addr ) { - t_CKFLOAT a = (*(t_CKCOMPLEX **)sp)->re; + // t_CKFLOAT a = (*(t_CKCOMPLEX **)sp)->re; push_( sp, (t_CKUINT)(&((*(t_CKCOMPLEX **)sp)->re)) ); } else { push_float( sp, (*(t_CKCOMPLEX **)sp)->re ); diff --git a/v2/chuck_main.cpp b/v2/chuck_main.cpp index 21f4d5d1..b11584da 100755 --- a/v2/chuck_main.cpp +++ b/v2/chuck_main.cpp @@ -294,6 +294,7 @@ static void usage() t_CKBOOL load_hid = FALSE; t_CKBOOL enable_server = TRUE; t_CKBOOL do_watchdog = TRUE; + t_CKINT adaptive_size = 0; t_CKINT log_level = CK_LOG_CORE; t_CKINT deprecate_level = 1; // warn @@ -404,6 +405,8 @@ static void usage() log_level = argv[i][9] ? atoi( argv[i]+9 ) : CK_LOG_INFO; else if( !strncmp(argv[i], "-v", 2) ) log_level = argv[i][2] ? atoi( argv[i]+2 ) : CK_LOG_INFO; + else if( !strncmp(argv[i], "--adaptive", 10) ) + adaptive_size = argv[i][10] ? atoi( argv[i]+10 ) : -1; else if( !strncmp(argv[i], "--deprecate", 11) ) { // get the rest @@ -494,6 +497,8 @@ static void usage() Chuck_VM::our_priority = g_priority; // set watchdog g_do_watchdog = do_watchdog; + // set adaptive size + if( adaptive_size < 0 ) adaptive_size = buffer_size; if ( !files && vm_halt && !enable_shell ) { @@ -527,7 +532,8 @@ static void usage() // allocate the vm - needs the type system vm = g_vm = new Chuck_VM; if( !vm->initialize( enable_audio, vm_halt, srate, buffer_size, - num_buffers, dac, adc, dac_chans, adc_chans, block ) ) + num_buffers, dac, adc, dac_chans, adc_chans, + block, adaptive_size ) ) { fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); exit( 1 ); diff --git a/v2/chuck_ugen.cpp b/v2/chuck_ugen.cpp index 34de11f7..a929f0a6 100755 --- a/v2/chuck_ugen.cpp +++ b/v2/chuck_ugen.cpp @@ -200,6 +200,10 @@ void Chuck_UGen::init() m_pan = 1.0f; m_next = 0.0f; m_use_next = FALSE; + + m_sum_v = NULL; + m_current_v = NULL; + m_last_v = NULL; shred = NULL; owner = NULL; @@ -230,6 +234,11 @@ void Chuck_UGen::done() fa_done( m_dest_list, m_dest_cap ); fa_done( m_src_uana_list, m_src_uana_cap ); fa_done( m_dest_uana_list, m_dest_uana_cap ); + + // reclaim + SAFE_DELETE_ARRAY( m_sum_v ); + SAFE_DELETE_ARRAY( m_current_v ); + SAFE_DELETE_ARRAY( m_last_v ); // TODO: m_multi_chan, break ref count loop } @@ -238,6 +247,33 @@ void Chuck_UGen::done() //----------------------------------------------------------------------------- +// name: alloc_v() +// desc: ... +//----------------------------------------------------------------------------- +t_CKBOOL Chuck_UGen::alloc_v( t_CKUINT size ) +{ + // reclaim + SAFE_DELETE_ARRAY( m_sum_v ); + SAFE_DELETE_ARRAY( m_current_v ); + SAFE_DELETE_ARRAY( m_last_v ); + + // go + if( size > 0 ) + { + m_sum_v = new SAMPLE[size]; + m_current_v = new SAMPLE[size]; + m_last_v = new SAMPLE[size]; + + return ( m_sum_v != NULL && m_current_v != NULL && m_last_v != NULL ); + } + + return TRUE; +} + + + + +//----------------------------------------------------------------------------- // name: alloc_multi_chan() // desc: ... //----------------------------------------------------------------------------- @@ -692,6 +728,130 @@ t_CKBOOL Chuck_UGen::system_tick( t_CKTIME now ) //----------------------------------------------------------------------------- +// name: tick_v() +// dsec: ... +//----------------------------------------------------------------------------- +t_CKBOOL Chuck_UGen::system_tick_v( t_CKTIME now, t_CKUINT numFrames ) +{ + if( m_time >= now ) + return m_valid; + + t_CKUINT i, j; Chuck_UGen * ugen; SAMPLE factor; + + // inc time + m_time = now; + // initial sum + // m_sum = 0.0f; + memset( m_sum_v, 0, numFrames * sizeof(SAMPLE) ); + if( m_num_src ) + { + ugen = m_src_list[0]; + if( ugen->m_time < now ) ugen->system_tick_v( now, numFrames ); + //m_sum = ugen->m_current; + memcpy( m_sum_v, ugen->m_current_v, numFrames * sizeof(SAMPLE) ); + + // tick the src list + for( i = 1; i < m_num_src; i++ ) + { + ugen = m_src_list[i]; + if( ugen->m_time < now ) ugen->system_tick_v( now, numFrames ); + if( ugen->m_valid ) + { + if( m_op <= 1 ) + for( j = 0; j < numFrames; j++ ) + m_sum_v[j] += ugen->m_current_v[j]; + // m_sum += ugen->m_current; + else // special ops + { + switch( m_op ) + { + case 2: for( j = 0; j < numFrames; j++ ) + m_sum_v[j] -= ugen->m_current_v[j]; break; + case 3: for( j = 0; j < numFrames; j++ ) + m_sum_v[j] *= ugen->m_current_v[j]; break; + case 4: for( j = 0; j < numFrames; j++ ) + m_sum_v[j] /= ugen->m_current_v[j]; break; + default: for( j = 0; j < numFrames; j++ ) + m_sum_v[j] += ugen->m_current_v[j]; break; + } + } + } + } + } + + // tick multiple channels + // multi = 0.0f; + if( m_multi_chan_size ) + { + // initialize + // memset( multi, 0, numFrames * sizeof(SAMPLE) ); + factor = 1.0f / m_multi_chan_size; + // iterate + for( i = 0; i < m_multi_chan_size; i++ ) + { + ugen = m_multi_chan[i]; + if( ugen->m_time < now ) ugen->system_tick_v( now, numFrames ); + // multiple channels are added + // multi += ugen->m_current; + for( j = 0; j < numFrames; j++ ) + m_sum_v[j] += ugen->m_current_v[j] * factor; + } + + // scale multi + // multi /= m_multi_chan_size; + // m_sum += multi; + } + + // if owner + if( owner != NULL && owner->m_time < now ) + owner->system_tick_v( now, numFrames ); + + if( m_op > 0 ) // UGEN_OP_TICK + { + // tick the ugen + if( tick ) + for( j = 0; j < numFrames; j++ ) + m_valid = tick( this, m_sum_v[j], &(m_current_v[j]), NULL ); + if( !m_valid ) + for( j = 0; j < numFrames; j++ ) + m_current_v[j] = 0.0f; + else + for( j = 0; j < numFrames; j++ ) + { + // apply gain and pan + m_current_v[j] *= m_gain * m_pan; + // dedenormal + CK_DDN( m_current_v[j] ); + // save as last + m_last_v[j] = m_current_v[j]; + } + return m_valid; + } + else if( m_op < 0 ) // UGEN_OP_PASS + { + for( j = 0; j < numFrames; j++ ) + { + // pass through + m_current_v[j] = m_sum_v[j]; + m_last_v[j] = m_current_v[j]; + } + return TRUE; + } + else // UGEN_OP_STOP + { + memset( m_current_v, 0, numFrames * sizeof(SAMPLE) ); + memset( m_last_v, 0, numFrames * sizeof(SAMPLE) ); + // m_current = 0.0f; + } + + // m_last = m_current; + return TRUE; +} + + + + +//----------------------------------------------------------------------------- // name: Chuck_UAna() // desc: constructor //----------------------------------------------------------------------------- diff --git a/v2/chuck_ugen.h b/v2/chuck_ugen.h index 16d72e8f..7372d3fc 100755 --- a/v2/chuck_ugen.h +++ b/v2/chuck_ugen.h @@ -72,6 +72,8 @@ public: // src t_CKBOOL is_connected_from( Chuck_UGen * src ); t_CKUINT disconnect( t_CKBOOL recursive ); t_CKUINT system_tick( t_CKTIME now ); + t_CKUINT system_tick_v( t_CKTIME now, t_CKUINT numFrames ); + t_CKBOOL alloc_v( t_CKUINT size ); protected: t_CKVOID add_by( Chuck_UGen * dest, t_CKBOOL isUpChuck ); @@ -117,6 +119,11 @@ public: // data SAMPLE m_gain; SAMPLE m_pan; t_CKINT m_op; + + // block processing + SAMPLE * m_sum_v; + SAMPLE * m_current_v; + SAMPLE * m_last_v; // the shred on which the ugen is created Chuck_VM_Shred * shred; diff --git a/v2/chuck_vm.cpp b/v2/chuck_vm.cpp index 0b02f0c3..c531d070 100755 --- a/v2/chuck_vm.cpp +++ b/v2/chuck_vm.cpp @@ -152,6 +152,8 @@ Chuck_VM::~Chuck_VM() } + + // dac tick //UGEN_TICK __dac_tick( Chuck_Object * SELF, SAMPLE in, SAMPLE * out ) //{ *out = in; return TRUE; } @@ -243,7 +245,7 @@ t_CKBOOL Chuck_VM::set_priority( t_CKINT priority, Chuck_VM * vm ) t_CKBOOL Chuck_VM::initialize( t_CKBOOL enable_audio, t_CKBOOL halt, t_CKUINT srate, t_CKUINT buffer_size, t_CKUINT num_buffers, t_CKUINT dac, t_CKUINT adc, t_CKUINT dac_chan, - t_CKUINT adc_chan, t_CKBOOL block ) + t_CKUINT adc_chan, t_CKBOOL block, t_CKUINT adaptive ) { if( m_init ) { @@ -275,6 +277,7 @@ t_CKBOOL Chuck_VM::initialize( t_CKBOOL enable_audio, t_CKBOOL halt, t_CKUINT sr m_shreduler = new Chuck_VM_Shreduler; m_shreduler->bbq = m_bbq; m_shreduler->rt_audio = enable_audio; + m_shreduler->set_adaptive( adaptive > 0 ? adaptive : 0 ); // log EM_log( CK_LOG_SYSTEM, "allocating messaging buffers..." ); @@ -298,6 +301,7 @@ t_CKBOOL Chuck_VM::initialize( t_CKBOOL enable_audio, t_CKBOOL halt, t_CKUINT sr { EM_log( CK_LOG_SYSTEM, "num buffers: %ld", num_buffers ); EM_log( CK_LOG_SYSTEM, "devices adc: %ld dac: %d (default 0)", adc, dac ); + EM_log( CK_LOG_SYSTEM, "adaptive block processing: %ld", adaptive > 1 ? adaptive : 0 ); } EM_log( CK_LOG_SYSTEM, "channels in: %ld out: %ld", adc_chan, dac_chan ); m_num_adc_channels = adc_chan; @@ -383,6 +387,7 @@ t_CKBOOL Chuck_VM::initialize_synthesis( ) m_bunghole->lock(); initialize_object( m_bunghole, &t_ugen ); m_bunghole->tick = NULL; + m_bunghole->alloc_v( m_shreduler->m_max_block_size ); m_shreduler->m_dac = m_dac; m_shreduler->m_adc = m_adc; m_shreduler->m_bunghole = m_bunghole; @@ -700,10 +705,12 @@ t_CKBOOL Chuck_VM::run( t_CKINT num_samps ) if( !m_audio_started ) start_audio(); // advance the shreduler - m_shreduler->advance(); - - // count - if( num_samps > 0 ) num_samps--; + if( !m_shreduler->m_adaptive ) + { + m_shreduler->advance(); + if( num_samps > 0 ) num_samps--; + } + else m_shreduler->advance_v( num_samps ); } return FALSE; @@ -1612,6 +1619,8 @@ Chuck_VM_Shreduler::Chuck_VM_Shreduler() m_bunghole = NULL; m_num_dac_channels = 0; m_num_adc_channels = 0; + + set_adaptive( 0 ); } @@ -1654,6 +1663,20 @@ t_CKBOOL Chuck_VM_Shreduler::shutdown() //----------------------------------------------------------------------------- +// name: set_adaptive() +// desc: ... +//----------------------------------------------------------------------------- +void Chuck_VM_Shreduler::set_adaptive( t_CKUINT max_block_size ) +{ + m_max_block_size = max_block_size > 1 ? max_block_size : 0; + m_adaptive = m_max_block_size > 1; + m_samps_until_next = -1; +} + + + + +//----------------------------------------------------------------------------- // name: add_blocked() // desc: add shred to the shreduler's blocked list //----------------------------------------------------------------------------- @@ -1729,6 +1752,7 @@ t_CKBOOL Chuck_VM_Shreduler::shredule( Chuck_VM_Shred * shred, } shred->wake_time = wake_time; + m_samps_until_next = wake_time - this->now_system; // list empty if( !shred_list ) @@ -1764,12 +1788,86 @@ t_CKBOOL Chuck_VM_Shreduler::shredule( Chuck_VM_Shred * shred, prev->next = shred; } } - + return TRUE; } + +//----------------------------------------------------------------------------- +// name: advance_v() +// desc: ... +//----------------------------------------------------------------------------- +void Chuck_VM_Shreduler::advance_v( t_CKINT & numLeft ) +{ + t_CKINT i, j, numFrames; + SAMPLE frame[128], gain[128], sum; + BBQ * audio = this->bbq; + + // compute number of frames to compute; update + numFrames = ck_min( m_max_block_size, numLeft ); + if( this->m_samps_until_next >= 1 ) + { + numFrames = (t_CKINT)(ck_min( numFrames, this->m_samps_until_next )); + this->m_samps_until_next -= numFrames; + } + numLeft -= numFrames; + + // advance system 'now' + this->now_system += numFrames; + + // tick in + if( rt_audio ) + { + for( j = 0; j < m_num_adc_channels; j++ ) + { + // update channel + m_adc->m_multi_chan[j]->m_time = this->now_system; + // cache gain + gain[j] = m_adc->m_multi_chan[j]->m_gain; + } + + // adaptive block + for( i = 0; i < numFrames; i++ ) + { + // get input + audio->digi_in()->tick_in( frame, m_num_adc_channels ); + // clear + sum = 0.0f; + // loop over channels + for( j = 0; j < m_num_adc_channels; j++ ) + { + m_adc->m_multi_chan[j]->m_current_v[i] = frame[j] * gain[j] * m_adc->m_gain; + sum += m_adc->m_multi_chan[j]->m_current_v[i]; + } + m_adc->m_last_v[i] = m_adc->m_current_v[i] = sum / m_num_adc_channels; + } + + // update time + m_adc->m_time = this->now_system; + } + + // dac + m_dac->system_tick_v( this->now_system, numFrames ); + + // suck samples + m_bunghole->system_tick_v( this->now_system, numFrames ); + + // adaptive block + for( i = 0; i < numFrames; i++ ) + { + for( j = 0; j < m_num_dac_channels; j++ ) + frame[j] = m_dac->m_multi_chan[j]->m_current_v[i]; + + // tick + audio->digi_out()->tick_out( frame, m_num_dac_channels ); + } +} + + + + //----------------------------------------------------------------------------- // name: advance2() // desc: ... @@ -1858,6 +1956,7 @@ void Chuck_VM_Shreduler::advance( ) + //----------------------------------------------------------------------------- // name: get() // desc: ... @@ -1868,7 +1967,10 @@ Chuck_VM_Shred * Chuck_VM_Shreduler::get( ) // list empty if( !shred ) + { + m_samps_until_next = -1; return NULL; + } // TODO: should this be <=? if( shred->wake_time <= ( this->now_system + .5 ) ) @@ -1881,7 +1983,10 @@ Chuck_VM_Shred * Chuck_VM_Shreduler::get( ) shred->prev = NULL; if( shred_list ) + { shred_list->prev = NULL; + m_samps_until_next = shred_list->wake_time - this->now_system; + } return shred; } diff --git a/v2/chuck_vm.h b/v2/chuck_vm.h index b6257b6c..efc46b51 100755 --- a/v2/chuck_vm.h +++ b/v2/chuck_vm.h @@ -291,6 +291,8 @@ public: // shreduling Chuck_VM_Shred * get( ); void advance( ); void advance2( ); + void advance_v( t_CKINT & num_left ); + void set_adaptive( t_CKUINT max_block_size ); public: // high-level shred interface t_CKBOOL remove( Chuck_VM_Shred * shred ); @@ -329,6 +331,11 @@ public: // status cache Chuck_VM_Status m_status; + + // max block size for adaptive block processing + t_CKUINT m_max_block_size; + t_CKBOOL m_adaptive; + t_CKDUR m_samps_until_next; }; @@ -353,7 +360,7 @@ public: // init t_CKUINT buffer_size = 512, t_CKUINT num_buffers = 4, t_CKUINT dac = 0, t_CKUINT adc = 0, t_CKUINT dac_chan = 2, t_CKUINT adc_chan = 2, - t_CKBOOL block = TRUE ); + t_CKBOOL block = TRUE, t_CKUINT adaptive = 0 ); t_CKBOOL initialize_synthesis( ); t_CKBOOL shutdown(); -- 2.11.4.GIT