Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
  /**
   * 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();
  }
Exemplo n.º 3
0
/* ------------------------------------------------------------------- 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();
}
Exemplo n.º 4
0
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();
}