int GRANSYNTH::run() { // NOTE: Without a lot more code, we can't guarantee that doupdate will // be called exactly every getSkip() samples, the way we can when not doing // block I/O. But this seems worth sacrificing for the clear performance // improvement that block I/O offers. const int frames = framesToRun(); int blockframes = min(frames, getSkip()); int framesdone = 0; while (1) { if (_branch <= 0) { doupdate(); _branch = getSkip(); } _branch -= blockframes; _stream->processBlock(_block, blockframes, _amp); rtbaddout(_block, blockframes); increment(blockframes); framesdone += blockframes; if (framesdone == frames) break; assert(framesdone < frames); const int remaining = frames - framesdone; if (remaining < blockframes) blockframes = remaining; } return frames; }
/** * For Lua instruments, the run method also performs the Lua * portion of the init method. That is because the init * method is called from the main RTcmix thread whereas the * run method is called from the traverse thread, but Lua * is not thread-safe and our Lua state management code * creates a separate Lua state for each thread. */ virtual int run() { //advise("LUAINST::run", "Began (thread %p)...", pthread_self()); int result = 0; if (state.parameters[2] != 0.0) { state.inputSampleCount = RTBUFSAMPS * inputChannels(); rtgetin(state.input, this, state.inputSampleCount); } lua_State *L = manageLuaState(); LuaInstrumentClass_t &luaInstrumentClass = manageLuaInstrumentClass(L, state.name); if (!luaInstrumentClass.initialized) { const char *luacode = luaCodeForInstrumentNames[state.name].c_str(); advise("LUAINST", "Defining Lua instrument code:\n\n%0.120s\n...\n", luacode); result = luaL_dostring(L, luacode); if (result == 0) { char init_function[0x100]; std::snprintf(init_function, 0x100, "%s_init", state.name); lua_getglobal(L, init_function); if (!lua_isnil(L, 1)) { luaInstrumentClass.init_key = luaL_ref(L, LUA_REGISTRYINDEX); lua_pop(L, 1); } else { exit(die("LUAINST", "Failed to register: %s.", init_function)); } char run_function[0x100]; std::snprintf(run_function, 0x100, "%s_run", state.name); lua_getglobal(L, run_function); if (!lua_isnil(L, 1)) { luaInstrumentClass.run_key = luaL_ref(L, LUA_REGISTRYINDEX); lua_pop(L, 1); } else { exit(die("LUAINST", "Failed to register: %s.", run_function)); } } else { warn("LUAINST", "Failed with: %d\n", result); } luaInstrumentClass.initialized = true; } if (!state.initialized) { lua_rawgeti(L, LUA_REGISTRYINDEX, luaInstrumentClass.init_key); lua_pushlightuserdata(L, &state); if (lua_pcall(L, 1, 1, 0) != 0) { rterror("LUAINST", "Lua error in \"%s_init\": %s.\n", state.name, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); state.initialized = true; } state.startFrame = state.endFrame; long frameCount = framesToRun(); state.endFrame += frameCount; doupdate(); lua_rawgeti(L, LUA_REGISTRYINDEX, luaInstrumentClass.run_key); lua_pushlightuserdata(L, &state); if (lua_pcall(L, 1, 1, 0) != 0) { die("LUAINST", "Lua error in \"%s_run\": %s with key %p frame %i.\n", state.name, lua_tostring(L, -1), luaInstrumentClass.run_key, state.currentFrame); exit(-1); } result = lua_tonumber(L, -1); lua_pop(L, 1); rtbaddout(state.output, frameCount); increment(frameCount); return framesToRun(); }
/* ------------------------------------------------------------------- run -- */ int SPECTACLE_BASE :: run() { if (first_time) { /* create segmented input buffer */ int num_segments = (window_len / RTBUFSAMPS) + 2; int extrasamps = RTBUFSAMPS - framesToRun(); if (extrasamps) num_segments++; int inbuf_samps = num_segments * RTBUFSAMPS * inputChannels(); inbuf = new float [inbuf_samps]; for (int i = 0; i < inbuf_samps; i++) inbuf[i] = 0.0; /* Read ptr chases write ptr by <window_len>. Set read ptr to a position <window_len> frames from right end of input buffer. Set write ptr to beginning of buffer, or, if framesToRun() is not the same as the RTcmix buffer size, set it so that the next run invocation after this one will find the write ptr at the start of the second buffer segment. */ inbuf_readptr = inbuf + (inbuf_samps - (window_len * inputChannels())); inbuf_startptr = inbuf + (extrasamps * inputChannels()); inbuf_writeptr = inbuf_startptr; inbuf_endptr = inbuf + inbuf_samps; int outbuf_samps = num_segments * RTBUFSAMPS * outputChannels(); outbuf = new float [outbuf_samps]; for (int i = 0; i < outbuf_samps; i++) outbuf[i] = 0.0; outbuf_readptr = outbuf + (outbuf_samps - (framesToRun() * outputChannels())); outbuf_writeptr = outbuf_readptr; outbuf_endptr = outbuf + outbuf_samps; first_time = 0; DPRINT3("framesToRun()=%d, extrasamps=%d, num_segments=%d\n", framesToRun(), extrasamps, num_segments); DPRINT3("inbuf_samps=%d, inbuf_readptr=%p, inbuf_writeptr=%p\n", inbuf_samps, inbuf_readptr, inbuf_writeptr); DPRINT3("outbuf_samps=%d, outbuf_readptr=%p, outbuf_writeptr=%p\n", outbuf_samps, outbuf_readptr, outbuf_writeptr); } const int insamps = framesToRun() * inputChannels(); if (currentFrame() < total_insamps) rtgetin(inbuf_writeptr, this, insamps); int iterations = framesToRun() / decimation; if (framesToRun() < RTBUFSAMPS) iterations++; DPRINT1("iterations=%d\n", iterations); for (int i = 0; i < iterations; i++) { if (currentFrame() < input_end_frame) { DPRINT1("taking input...cursamp=%d\n", currentFrame()); shiftin(); fold(currentFrame()); JGrfft(fft_buf, half_fft_len, FORWARD); leanconvert(); } else flush_dry_delay(); modify_analysis(); leanunconvert(); JGrfft(fft_buf, half_fft_len, INVERSE); overlapadd(currentFrame()); shiftout(); increment(decimation); } if (currentFrame() < input_end_frame) { inbuf_writeptr += insamps; if (inbuf_writeptr >= inbuf_endptr) inbuf_writeptr = inbuf; } rtbaddout(outbuf_readptr, framesToRun()); outbuf_readptr += framesToRun() * outputChannels(); if (outbuf_readptr >= outbuf_endptr) outbuf_readptr = outbuf; return framesToRun(); }
int PVOC::run() { #ifdef debug printf("PVOC::run\n\n"); #endif // This runs the engine forward until the first buffer of output data is ready (see PVOC::shiftout()). // This compensates for the group delay of the windowed output. int outFramesNeeded = framesToRun(); if (_cachedOutFrames) { int toCopy = min(_cachedOutFrames, outFramesNeeded); if (toCopy >= 0) { #ifdef debug printf("\twriting %d of %d leftover frames from _outbuf at offset %d to rtbaddout\n", toCopy, _cachedOutFrames, _outReadOffset); #endif rtbaddout(&_outbuf[_outReadOffset], toCopy); increment(toCopy); _outReadOffset += toCopy; assert(_outReadOffset <= _outWriteOffset); if (_outReadOffset == _outWriteOffset) _outReadOffset = _outWriteOffset = 0; #ifdef debug printf("\t_outbuf read offset %d, write offset %d\n", _outReadOffset, _outWriteOffset); #endif outFramesNeeded -= toCopy; _cachedOutFrames -= toCopy; } } while (outFramesNeeded > 0) { #ifdef debug printf("\ttop of loop: needed=%d _in=%d _on=%d Nw=%d\n", outFramesNeeded, _in, _on, Nw); #endif /* * analysis: input D samples; window, fold and rotate input * samples into FFT buffer; take FFT; and convert to * amplitude-frequency (phase vocoder) form */ shiftin( _pvInput, Nw, D); /* * increment times */ _in += D; _on += I; if ( Np ) { ::vvmult( winput, Hwin, _pvInput, Nw ); lpcoef[0] = ::lpa( winput, Nw, lpcoef, Np ); /* printf("%.3g/", lpcoef[0] ); */ } ::fold( _pvInput, Wanal, Nw, _fftBuf, N, _in ); ::rfft( _fftBuf, N2, FORWARD ); convert( _fftBuf, channel, N2, D, R ); // if ( I == 0 ) { // if ( Np ) // fwrite( lpcoef, sizeof(float), Np+1, stdout ); // fwrite( channel, sizeof(float), N+2, stdout ); // fflush( stdout ); // /* printf("\n" ); // continue; // } /* * at this point channel[2*i] contains amplitude data and * channel[2*i+1] contains frequency data (in Hz) for phase * vocoder channels i = 0, 1, ... N/2; the center frequency * associated with each channel is i*f, where f is the * fundamental frequency of analysis R/N; any desired spectral * modifications can be made at this point: pitch modifications * are generally well suited to oscillator bank resynthesis, * while time modifications are generally well (and more * efficiently) suited to overlap-add resynthesis */ if (_pvFilter) { _pvFilter->run(channel, N2); } if ( obank ) { /* * oscillator bank resynthesis */ oscbank( channel, N2, lpcoef, Np, R, Nw, I, P, _pvOutput ); #if defined(debug) && 0 printf("osc output (first 16):\n"); for (int x=0; x<16; ++x) printf("%g ",_pvOutput[x]); printf("\n"); #endif shiftout( _pvOutput, Nw, I, _on+Nw-I); } else { /* * overlap-add resynthesis */ unconvert( channel, _fftBuf, N2, I, R ); ::rfft( _fftBuf, N2, INVERSE ); ::overlapadd( _fftBuf, N, Wsyn, _pvOutput, Nw, _on ); // I samples written into _outbuf shiftout( _pvOutput, Nw, I, _on); } // Handle case where last synthesized block extended beyond outFramesNeeded int framesToOutput = ::min(outFramesNeeded, I); #ifdef debug printf("\tbottom of loop. framesToOutput: %d\n", framesToOutput); #endif int framesAvailable = _outWriteOffset - _outReadOffset; framesToOutput = ::min(framesToOutput, framesAvailable); if (framesToOutput > 0) { #ifdef debug printf("\twriting %d frames from offset %d to rtbaddout\n", framesToOutput, _outReadOffset); #endif rtbaddout(&_outbuf[_outReadOffset], framesToOutput); increment(framesToOutput); _outReadOffset += framesToOutput; if (_outReadOffset == _outWriteOffset) _outReadOffset = _outWriteOffset = 0; } _cachedOutFrames = _outWriteOffset - _outReadOffset; #ifdef debug if (_cachedOutFrames > 0) { printf("\tsaving %d samples left over\n", _cachedOutFrames); } printf("\toutbuf read offset %d, write offset %d\n\n", _outReadOffset, _outWriteOffset); #endif outFramesNeeded -= framesToOutput; } /* while (outFramesNeeded > 0) */ return framesToRun(); }
int LPCIN::run() { int n = 0; float out[2]; /* Space for only 2 output chans! */ const int inchans = inputChannels(); // Samples may have been left over from end of previous run's block if (_leftOver > 0) { int toAdd = min(_leftOver, framesToRun()); #ifdef debug printf("using %d leftover samps starting at offset %d\n", _leftOver, _savedOffset); #endif bmultf(&_alpvals[_savedOffset], _ampmlt, toAdd); // Scale signal rtbaddout(&_alpvals[_savedOffset], toAdd); increment(toAdd); n += toAdd; _leftOver -= toAdd; _savedOffset += toAdd; } /* framesToRun() returns the number of sample frames -- 1 sample for each channel -- that we have to write during this scheduler time slice. */ for (; n < framesToRun(); n += _counter) { double p[10]; update(p, LPCIN_bw + 1); _amp = p[LPCIN_amp]; _warpFactor = p[LPCIN_warp]; _reson_is_on = p[LPCIN_cf] ? true : false; _cf_fact = p[LPCIN_cf]; _bw_fact = p[LPCIN_bw]; int loc; _frameno = _frame1 + ((float)(currentFrame())/nSamps()) * _frames; #ifdef debug printf("\tgetting frame %g of %d (%d out of %d signal samps)\n", _frameno, (int)_frames, currentFrame(), nSamps()); #endif if (_dataSet->getFrame(_frameno,_coeffs) == -1) break; // If requested, stabilize this frame before using if (_autoCorrect) stabilize(_coeffs, _nPoles); _ampmlt = _amp * _coeffs[RESIDAMP] / 10000.0; // XXX normalize this! float newpch = (_coeffs[PITCH] > 0.0) ? _coeffs[PITCH] : 64.0; if (_coeffs[RMSAMP] < _cutoff) _ampmlt = 0; if (_reson_is_on) { /* Treat _cf_fact as absolute freq. If _bw_fact is greater than 20, treat as absolute freq. Else treat as factor (i.e., cf * factor == bw). */ float cf = _cf_fact; float bw = (_bw_fact < 20.0) ? cf * _bw_fact : _bw_fact; rszset(SR, cf, bw, 1., _rsnetc); /* printf("%f %f %f %f\n",_cf_fact*cps, _bw_fact*_cf_fact*cps,_cf_fact,_bw_fact,cps); */ } float *cpoint = _coeffs + 4; if (_warpFactor != 0.0) { float warp = (_warpFactor > 1.) ? .0001 : _warpFactor; _ampmlt *= _warpPole.set(warp, cpoint, _nPoles); } _counter = int(((float)SR/(newpch * /*_perperiod*/ 1.0) ) * .5); // _counter = (RTBUFSAMPS < MAXVALS) ? RTBUFSAMPS : MAXVALS; // _counter = (_counter > (nSamps() - currentFrame())) ? nSamps() - currentFrame() : _counter; _counter = min(_counter, framesToRun() - n); if (_counter <= 0) break; rtgetin(_inbuf, this, _counter); // Deinterleave input for (int from=_inChannel, to=0; to < _counter; from += inchans, ++to) _buzvals[to] = _inbuf[from]; #ifdef debug printf("\t _buzvals[0] = %g\n", _buzvals[0]); #endif if (_warpFactor) { // float warp = (_warpFactor > 1.) ? shift(_coeffs[PITCH],newpch,(float)SR) : _warpFactor; float warp = _warpFactor; #ifdef debug printf("\tpch: %f newpch: %f d: %f\n",_coeffs[PITCH], newpch, warp); #endif /************* warp = ABS(warp) > .2 ? SIGN(warp) * .15 : warp; ***************/ _warpPole.run(_buzvals, warp, cpoint, _alpvals, _counter); } else { ballpole(_buzvals,&_jcount,_nPoles,_past,cpoint,_alpvals,_counter); } #ifdef debug { int x; float maxamp=0; for (x=0;x<_counter;x++) { if (ABS(_alpvals[x]) > ABS(maxamp)) maxamp = _alpvals[x]; } printf("\t maxamp = %g\n", maxamp); } #endif if (_reson_is_on) bresonz(_alpvals,_rsnetc,_alpvals,_counter); int sampsToAdd = min(_counter, framesToRun() - n); // printf("\tscaling %d samples by %g\n", sampsToAdd, _ampmlt); bmultf(_alpvals, _ampmlt, sampsToAdd); // Scale signal /* Write this block to the output buffer. */ rtbaddout(_alpvals, sampsToAdd); /* Keep track of how many sample frames this instrument has generated. */ increment(sampsToAdd); } // Handle case where last synthesized block extended beyond framesToRun() if (n > framesToRun()) { _leftOver = n - framesToRun(); _savedOffset = _counter - _leftOver; #ifdef debug printf("saving %d samples left over at offset %d\n", _leftOver, _savedOffset); #endif } return framesToRun(); }
/* Called by the scheduler for every time slice in which this instrument should run. This is where the real work of the instrument is done. */ int LPCPLAY::run() { int n = 0; float out[2]; /* Space for only 2 output chans! */ #if 0 printf("\nLPCPLAY::run()\n"); #endif // Samples may have been left over from end of previous run's block if (_leftOver > 0) { int toAdd = min(_leftOver, framesToRun()); #ifdef debug printf("using %d leftover samps starting at offset %d\n", _leftOver, _savedOffset); #endif rtbaddout(&_alpvals[_savedOffset], toAdd); increment(toAdd); n += toAdd; _leftOver -= toAdd; _savedOffset += toAdd; } /* framesToRun() returns the number of sample frames -- 1 sample for each channel -- that we have to write during this scheduler time slice. */ for (; n < framesToRun(); n += _counter) { double p[12]; update(p, 12); _amp = p[2]; _pitch = p[3]; _transposition = ABS(_pitch); _warpFactor = p[6]; _reson_is_on = p[7] ? true : false; _cf_fact = p[7]; _bw_fact = p[8]; int loc; if ( _unvoiced_rate && !_voiced ) { ++_frameno; /* if unvoiced set to normal rate */ } else { _frameno = _frame1 + ((float)(currentFrame())/nSamps()) * _frames; } #if 0 printf("frame %g\n", _frameno); #endif if (_dataSet->getFrame(_frameno,_coeffs) == -1) break; // If requested, stabilize this frame before using if (_autoCorrect) stabilize(_coeffs, _nPoles); float buzamp = getVoicedAmp(_coeffs[THRESH]); _voiced = (buzamp > 0.1); /* voiced = 0 for 10:1 noise */ float noisamp = (1.0 - buzamp) * _randamp; /* for now */ _ampmlt = _amp * _coeffs[RESIDAMP]; if (_coeffs[RMSAMP] < _cutoff) _ampmlt = 0; float cps = tablei(currentFrame(),_pchvals,_tblvals); float newpch = cps; // If input pitch was specified as -X.YZ, use this as actual pitch if ((_pitch < 0) && (ABS(_pitch) >= 1)) newpch = _transposition; if (_reson_is_on) { /* If _cf_fact is greater than 20, treat as absolute freq. Else treat as factor. If _bw_fact is greater than 20, treat as absolute freq. Else treat as factor (i.e., cf * factor == bw). */ float cf = (_cf_fact < 20.0) ? _cf_fact*cps : _cf_fact; float bw = (_bw_fact < 20.0) ? cf * _bw_fact : _bw_fact; rszset(SR, cf, bw, 1., _rsnetc); #ifdef debug printf("cf %g bw %g cps %g\n", cf, bw,cps); #endif } float si = newpch * _magic; float *cpoint = _coeffs + 4; if (_warpFactor != 0.0) { float warp = (_warpFactor > 1.) ? .0001 : _warpFactor; _ampmlt *= _warpPole.set(warp, cpoint, _nPoles); } if (_hnfactor < 1.0) { buzamp *= _hnfactor; /* compensate for gain increase */ } float hn = (_hnfactor <= 1.0) ? (int)(_hnfactor*_srd2/newpch)-2 : _hnfactor; _counter = int(((float)SR/(newpch * _perperiod) ) * .5); _counter = (_counter > (nSamps() - currentFrame())) ? nSamps() - currentFrame() : _counter; #ifdef debug printf("fr: %g err: %g bzamp: %g noisamp: %g pch: %g ctr: %d\n", _frameno,_coeffs[THRESH],_ampmlt*buzamp,_ampmlt*noisamp,newpch,_counter); #endif if (_counter <= 0) break; // Catch bad pitches which generate array overruns else if (_counter > _arrayLen) { rtcmix_warn("LPCPLAY", "Counter exceeded array size -- limiting. Frame pitch: %f", newpch); _counter = _arrayLen; } bbuzz(_ampmlt*buzamp,si,hn,_sineFun,&_phs,_buzvals,_counter); #ifdef debug printf("\t _buzvals[0] = %g\n", _buzvals[0]); #endif l_brrand(_ampmlt*noisamp,_noisvals,_counter); /* TEMPORARY */ #ifdef debug printf("\t _noisvals[0] = %g\n", _noisvals[0]); #endif for (loc=0; loc<_counter; loc++) { _buzvals[loc] += _noisvals[loc]; /* add voiced and unvoiced */ } if (_warpFactor) { float warp = (_warpFactor > 1.) ? shift(_coeffs[PITCH],newpch,(float)SR) : _warpFactor; #ifdef debug printf("\tpch: %f newpch: %f d: %f\n",_coeffs[PITCH], newpch, warp); #endif /************* warp = ABS(warp) > .2 ? SIGN(warp) * .15 : warp; ***************/ _warpPole.run(_buzvals, warp, cpoint, _alpvals, _counter); } else { ballpole(_buzvals,&_jcount,_nPoles,_past,cpoint,_alpvals,_counter); } #ifdef debug { int x; float maxamp=0; for (x=0;x<_counter;x++) { if (ABS(_alpvals[x]) > ABS(maxamp)) maxamp = _alpvals[x]; } printf("\t maxamp = %g\n", maxamp); } #endif if (_reson_is_on) bresonz(_alpvals,_rsnetc,_alpvals,_counter); // Apply envelope last float envelope = evp(currentFrame(),_envFun,_envFun,_evals); bmultf(_alpvals, envelope, _counter); int sampsToAdd = min(_counter, framesToRun() - n); /* Write this block to the output buffer. */ rtbaddout(_alpvals, sampsToAdd); /* Keep track of how many sample frames this instrument has generated. */ increment(sampsToAdd); } // Handle case where last synthesized block extended beyond framesToRun() if (n > framesToRun()) { _leftOver = n - framesToRun(); _savedOffset = _counter - _leftOver; #ifdef debug printf("saving %d samples left over at offset %d\n", _leftOver, _savedOffset); #endif } return framesToRun(); }