t_CKBOOL MidiInManager::open( MidiIn * min, t_CKINT device_num ) { // see if port not already open if( device_num >= (t_CKINT)the_mins.capacity() || !the_mins[device_num] ) { // allocate the buffer CBufferAdvance * cbuf = new CBufferAdvance; if( !cbuf->initialize( BUFFER_SIZE, sizeof(MidiMsg) ) ) { if( !min->m_suppress_output ) EM_error2( 0, "MidiIn: couldn't allocate CBuffer for port %i...", device_num ); delete cbuf; return FALSE; } // allocate RtMidiIn * rtmin = new RtMidiIn; try { rtmin->openPort( device_num ); rtmin->setCallback( cb_midi_input, cbuf ); } catch( RtError & err ) { if( !min->m_suppress_output ) { // print it EM_error2( 0, "MidiIn: couldn't open MIDI port %i...", device_num ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } delete cbuf; return FALSE; } // resize? if( device_num >= (t_CKINT)the_mins.capacity() ) { t_CKINT size = the_mins.capacity() * 2; if( device_num >= size ) size = device_num + 1; the_mins.resize( size ); the_bufs.resize( size ); } // put cbuf and rtmin in vector for future generations the_mins[device_num] = rtmin; the_bufs[device_num] = cbuf; } // set min min->min = the_mins[device_num]; // found min->m_buffer = the_bufs[device_num]; // get an index into your (you are min here) own buffer, // and a free ticket to your own workshop min->m_read_index = min->m_buffer->join( (Chuck_Event *)min->SELF ); min->m_device_num = (t_CKUINT)device_num; // done return TRUE; }
t_CKBOOL MidiOutManager::open( MidiOut * mout, const std::string & name ) { t_CKINT device_num = -1; try { RtMidiOut * rtmout = new RtMidiOut; t_CKINT count = rtmout->getPortCount(); for(t_CKINT i = 0; i < count; i++) { std::string port_name = rtmout->getPortName( i ); if( port_name == name ) { device_num = i; break; } } if( device_num == -1 ) { // search by substring for(t_CKINT i = 0; i < count; i++) { std::string port_name = rtmout->getPortName( i ); if( port_name.find( name ) != std::string::npos ) { device_num = i; break; } } } } catch( RtMidiError & err ) { if( !mout->m_suppress_output ) { // print it EM_error2( 0, "MidiOut: error locating MIDI port named %s", name.c_str() ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } return FALSE; } if(device_num == -1) { EM_error2( 0, "MidiOut: error locating MIDI port named %s", name.c_str() ); return FALSE; } t_CKBOOL result = open( mout, device_num ); return result; }
t_CKBOOL EM_reset( c_str fname, FILE * fd ) { anyErrors = FALSE; fileName = fname ? fname : (c_str)""; lineNum = 1; EM_lineNum = 1; linePos = intList( 0, NULL ); // if( yyin ) fclose( yyin ); if( fd ) yyin = fd; else yyin = fopen( fname, "r" ); if (!yyin) EM_error2( 0, "no such file or directory" ); else fseek( yyin, 0, SEEK_SET ); EM_lineNum = 0; return (yyin != 0); }
//----------------------------------------------------------------------------- // name: probe() // desc: ... //----------------------------------------------------------------------------- void Digitalio::probe() { #ifndef __DISABLE_RTAUDIO__ RtAudio * rta = NULL; RtAudio::DeviceInfo info; // allocate RtAudio try { rta = new RtAudio( ); } catch( RtError err ) { // problem finding audio devices, most likely EM_error2b( 0, "%s", err.getMessage().c_str() ); return; } // get count int devices = rta->getDeviceCount(); EM_error2b( 0, "found %d device(s) ...", devices ); // EM_error2( 0, "--------------------------" ); EM_reset_msg(); // loop for( int i = 0; i < devices; i++ ) { try { info = rta->getDeviceInfo(i); } catch( RtError & error ) { error.printMessage(); break; } // print EM_error2b( 0, "------( audio device: %d )---------------", i+1 ); print( info ); // skip if( i < devices ) EM_error2( 0, "" ); EM_reset_msg(); } delete rta; #endif // __DISABLE_RTAUDIO__ return; }
t_CKBOOL MidiOutManager::open( MidiOut * mout, t_CKINT device_num ) { // see if port not already open if( device_num >= (t_CKINT)the_mouts.capacity() || !the_mouts[device_num] ) { // allocate RtMidiOut * rtmout = new RtMidiOut; try { rtmout->openPort( device_num ); } catch( RtError & err ) { if( !mout->m_suppress_output ) { // print it EM_error2( 0, "MidiOut: couldn't open MIDI port %i...", device_num ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } return FALSE; } // resize? if( device_num >= (t_CKINT)the_mouts.capacity() ) { t_CKINT size = the_mouts.capacity() * 2; if( device_num >= size ) size = device_num + 1; the_mouts.resize( size ); } // put rtmout in vector for future generations the_mouts[device_num] = rtmout; } // found (always) (except when it doesn't get here) mout->mout = the_mouts[device_num]; mout->m_device_num = (t_CKUINT)device_num; // done return TRUE; }
//----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::initialize( DWORD__ num_channels, DWORD__ sampling_rate, DWORD__ bps, DWORD__ buffer_size, DWORD__ num_buffers ) { if( m_init ) return FALSE; m_num_channels_out = num_channels; m_num_channels_in = num_channels; m_sampling_rate = sampling_rate; m_bps = bps; m_buffer_size = buffer_size; m_num_buffers = num_buffers; m_start = 0; m_tick_count = 0; m_go = 0; m_end = 0; // allocate RtAudio try { m_rtaudio = new RtAudio( ); } catch( RtError err ) { // problem finding audio devices, most likely EM_error2( 0, "%s", err.getMessageString() ); return m_init = FALSE; } // open device try { m_rtaudio->openStream( m_dac_n, m_num_channels_out, m_adc_n, m_num_channels_in, RTAUDIO_FLOAT32, sampling_rate, (int *)&m_buffer_size, num_buffers ); if( m_use_cb ) m_rtaudio->setStreamCallback( &cb, NULL ); } catch( RtError err ) { try { m_buffer_size = buffer_size; // try output only m_rtaudio->openStream( m_dac_n, m_num_channels_out, 0, 0, RTAUDIO_FLOAT32, sampling_rate, (int *)&m_buffer_size, num_buffers ); if( m_use_cb ) m_rtaudio->setStreamCallback( &cb, NULL ); } catch( RtError err ) { EM_error2( 0, "%s", err.getMessageString() ); SAFE_DELETE( m_rtaudio ); return m_init = FALSE; } } if( m_use_cb ) { m_buffer_in = new SAMPLE[m_buffer_size * num_channels]; m_buffer_out = new SAMPLE[m_buffer_size * num_channels]; memset( m_buffer_in, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); memset( m_buffer_out, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); m_read_ptr = NULL; m_write_ptr = NULL; } m_in_ready = FALSE; m_out_ready = FALSE; return m_init = TRUE; }
//----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::initialize( DWORD__ num_dac_channels, DWORD__ num_adc_channels, DWORD__ sampling_rate, DWORD__ bps, DWORD__ buffer_size, DWORD__ num_buffers, DWORD__ block, Chuck_VM * vm_ref, BOOL__ rt_audio, void * callback, void * data, BOOL__ force_srate ) { if( m_init ) return FALSE; m_num_channels_out = num_dac_channels; m_num_channels_in = num_adc_channels; m_sampling_rate = sampling_rate; m_bps = bps; m_buffer_size = buffer_size; m_num_buffers = num_buffers; m_start = 0; m_tick_count = 0; m_go = 0; m_end = 0; m_block = block; DWORD__ num_channels; unsigned int bufsize = m_buffer_size; // log EM_log( CK_LOG_FINE, "initializing RtAudio..." ); // push indent EM_pushlog(); // if rt_audio is false, then set block to FALSE to avoid deadlock if( !rt_audio ) m_block = FALSE; #ifndef __DISABLE_RTAUDIO__ // if real-time audio if( rt_audio ) { // allocate RtAudio try { m_rtaudio = new RtAudio( ); } catch( RtError err ) { // problem finding audio devices, most likely EM_error2( 0, "%s", err.getMessage().c_str() ); return m_init = FALSE; } // convert 1-based ordinal to 0-based ordinal (added 1.3.0.0) // note: this is to preserve previous devices numbering after RtAudio change if( m_num_channels_out > 0 ) { // check output device number; 0 used to mean "default" bool useDefault = ( m_dac_n == 0 ); // default (refactor 1.3.1.2) if( useDefault ) { // get the default m_dac_n = m_rtaudio->getDefaultOutputDevice(); } else { m_dac_n -= 1; } // get device info RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_dac_n); // ensure correct channel count if default device is requested if( useDefault ) { // check if( device_info.outputChannels < m_num_channels_out ) { // find first device with at least the requested channel count m_dac_n = -1; int num_devices = m_rtaudio->getDeviceCount(); for( int i = 0; i < num_devices; i++ ) { device_info = m_rtaudio->getDeviceInfo(i); if(device_info.outputChannels >= m_num_channels_out) { m_dac_n = i; break; } } // check for error if( m_dac_n == -1 ) { EM_error2( 0, "no audio output device with requested channel count (%i)...", m_num_channels_out ); return m_init = FALSE; } } } // index of closest sample rate long closestIndex = -1; // difference of closest so far long closestDiff = LONG_MAX; // the next highest long nextHighest = -1; // diff to next highest so far long diffToNextHighest = LONG_MAX; // check if request sample rate in support rates (added 1.3.1.2) for( long i = 0; i < device_info.sampleRates.size(); i++ ) { // difference long diff = device_info.sampleRates[i] - sampling_rate; // check // ge: changed from abs to labs, 2015.11 if( ::labs(diff) < closestDiff ) { // remember index closestIndex = i; // update diff closestDiff = ::labs(diff); } // for next highest if( diff > 0 && diff < diffToNextHighest ) { // remember index nextHighest = i; // update diff diffToNextHighest = diff; } } // see if we found exact match (added 1.3.1.2) if( closestDiff != 0 ) { // check if( force_srate ) { // request sample rate not found, error out EM_error2( 0, "unsupported sample rate (%d) requested...", sampling_rate ); EM_error2( 0, "| (try --probe to enumerate available sample rates)" ); return m_init = FALSE; } // use next highest if available if( nextHighest >= 0 ) { // log EM_log( CK_LOG_SEVERE, "new sample rate (next highest): %d -> %d", sampling_rate, device_info.sampleRates[nextHighest] ); // update sampling rate m_sampling_rate = sampling_rate = device_info.sampleRates[nextHighest]; } else if( closestIndex >= 0 ) // nothing higher { // log EM_log( CK_LOG_SEVERE, "new sample rate (closest): %d -> %d", sampling_rate, device_info.sampleRates[closestIndex] ); // update sampling rate m_sampling_rate = sampling_rate = device_info.sampleRates[closestIndex]; } else { // nothing to do (will fail and throw error message when opening) } } } // convert 1-based ordinal to 0-based ordinal if( m_num_channels_in > 0 ) { if( m_adc_n == 0 ) { m_adc_n = m_rtaudio->getDefaultInputDevice(); // ensure correct channel count if default device is requested RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_adc_n); // check if input channels > 0 if( device_info.inputChannels < m_num_channels_in ) { // find first device with at least the requested channel count m_adc_n = -1; int num_devices = m_rtaudio->getDeviceCount(); for(int i = 0; i < num_devices; i++) { device_info = m_rtaudio->getDeviceInfo(i); if(device_info.inputChannels >= m_num_channels_in) { m_adc_n = i; break; } } // changed 1.3.1.2 (ge): for input, if nothing found, we just gonna try to open half-duplex if( m_adc_n == -1 ) { // set to 0 m_num_channels_in = 0; // problem finding audio devices, most likely // EM_error2( 0, "unable to find audio input device with requested channel count (%i)...", m_num_channels_in); // return m_init = FALSE; } } } else { m_adc_n -= 1; } } // open device try { // log EM_log( CK_LOG_FINE, "trying %d input %d output...", m_num_channels_in, m_num_channels_out ); RtAudio::StreamParameters output_parameters; output_parameters.deviceId = m_dac_n; output_parameters.nChannels = m_num_channels_out; output_parameters.firstChannel = 0; RtAudio::StreamParameters input_parameters; input_parameters.deviceId = m_adc_n; input_parameters.nChannels = m_num_channels_in; input_parameters.firstChannel = 0; RtAudio::StreamOptions stream_options; stream_options.flags = 0; stream_options.numberOfBuffers = num_buffers; stream_options.streamName = "ChucK"; stream_options.priority = 0; // open RtAudio m_rtaudio->openStream( m_num_channels_out > 0 ? &output_parameters : NULL, m_num_channels_in > 0 ? &input_parameters : NULL, CK_RTAUDIO_FORMAT, sampling_rate, &bufsize, m_use_cb ? ( block ? &cb : &cb2 ) : NULL, vm_ref, &stream_options ); } catch( RtError err ) { // log EM_log( CK_LOG_INFO, "exception caught: '%s'...", err.getMessage().c_str() ); EM_error2( 0, "%s", err.getMessage().c_str() ); SAFE_DELETE( m_rtaudio ); return m_init = FALSE; } // check bufsize if( bufsize != (int)m_buffer_size ) { EM_log( CK_LOG_SEVERE, "new buffer size: %d -> %i", m_buffer_size, bufsize ); m_buffer_size = bufsize; } // pop indent EM_poplog(); } #endif // __DISABLE_RTAUDIO__ #if defined(__CHIP_MODE__) if( !MoAudio::init( sampling_rate, buffer_size, 2 ) ) { EM_error2( 0, "%s", "(chuck)error: unable to initialize MoAudio..." ); return m_init = FALSE; } #endif // __CHIP_MODE__ if( m_use_cb ) { num_channels = num_dac_channels > num_adc_channels ? num_dac_channels : num_adc_channels; // log EM_log( CK_LOG_SEVERE, "allocating buffers for %d x %d samples...", m_buffer_size, num_channels ); // allocate buffers m_buffer_in = new SAMPLE[m_buffer_size * num_channels]; m_buffer_out = new SAMPLE[m_buffer_size * num_channels]; memset( m_buffer_in, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); memset( m_buffer_out, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); m_read_ptr = NULL; m_write_ptr = NULL; } m_in_ready = FALSE; m_out_ready = FALSE; return m_init = TRUE; }