Пример #1
0
void
SetPortValue::execute(ProcessContext& context)
{
	Event::execute(context);
	assert(_time >= context.start() && _time <= context.end());

	if (_port && _port->context() == Context::MESSAGE)
		return;

	apply(context);
	_engine.control_bindings()->port_value_changed(context, _port);
}
Пример #2
0
MD5::MD5 (const String& text)
{
    ProcessContext context;
    String::CharPointerType t (text.getCharPointer());

    while (! t.isEmpty())
    {
        // force the string into integer-sized unicode characters, to try to make it
        // get the same results on all platforms + compilers.
        uint32 unicodeChar = ByteOrder::swapIfBigEndian ((uint32) t.getAndAdvance());

        context.processBlock (&unicodeChar, sizeof (unicodeChar));
    }

    context.finish (result);
}
Пример #3
0
bool
PortImpl::apply_poly(ProcessContext& context, Raul::Maid& maid, uint32_t poly)
{
	if (_parent->path().is_root() ||
	    (_type == PortType::ATOM && !_value.is_valid())) {
		return false;
	}

	if (!_prepared_voices) {
		return true;
	}

	assert(poly == _prepared_voices->size());

	_poly = poly;

	// Apply a new set of voices from a preceding call to prepare_poly
	maid.dispose(set_voices(context, _prepared_voices));
	assert(_voices == _prepared_voices);
	_prepared_voices = NULL;

	if (is_a(PortType::CONTROL) || is_a(PortType::CV)) {
		set_control_value(context, context.start(), _value.get<float>());
	}

	assert(_voices->size() >= poly);
	assert(this->poly() == poly);
	assert(!_prepared_voices);

	return true;
}
Пример #4
0
void
JackDriver::post_process_port(ProcessContext& context, EnginePort* port)
{
	const SampleCount nframes    = context.nframes();
	jack_port_t*      jack_port  = (jack_port_t*)port->handle();
	PortImpl*         graph_port = port->graph_port();
	void*             buffer     = port->buffer();

	if (graph_port->is_input()) {
		return;
	}

	if (!buffer) {
		// First cycle for a new output, so pre_process wasn't called
		buffer = jack_port_get_buffer(jack_port, nframes);
		port->set_buffer(buffer);
	}

	graph_port->post_process(context);
	Buffer* const graph_buf = graph_port->buffer(0).get();
	if (graph_port->is_a(PortType::AUDIO)) {
		memcpy(buffer, graph_buf->samples(), nframes * sizeof(Sample));
	} else if (graph_port->buffer_type() == graph_port->bufs().uris().atom_Sequence) {
		jack_midi_clear_buffer(buffer);
		LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)graph_buf->atom();
		LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
			const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body);
			if (ev->body.type == graph_port->bufs().uris().midi_MidiEvent) {
				jack_midi_event_write(buffer, ev->time.frames, buf, ev->body.size);
			}
		}
	}
Пример #5
0
/** Run the patch for the specified number of frames.
 *
 * Calls all Nodes in (roughly, if parallel) the order _compiled_patch specifies.
 */
void
PatchImpl::process(ProcessContext& context)
{
	if (!_process)
		return;

	NodeImpl::pre_process(context);

	// Run all nodes
	if (_compiled_patch && _compiled_patch->size() > 0) {
		if (context.slaves().size() > 0) {
			process_parallel(context);
		} else {
			process_single(context);
		}
	}

	// Queue any cross-context connections
	for (CompiledPatch::QueuedConnections::iterator i = _compiled_patch->queued_connections.begin();
			i != _compiled_patch->queued_connections.end(); ++i) {
		(*i)->queue(context);
	}

	NodeImpl::post_process(context);
}
Пример #6
0
bool
PatchImpl::apply_internal_poly(ProcessContext& context, BufferFactory& bufs, Raul::Maid& maid, uint32_t poly)
{
	ThreadManager::assert_thread(THREAD_PROCESS);

	// TODO: Subpatch dynamic polyphony (i.e. changing port polyphony)

	for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i)
		(*i)->apply_poly(maid, poly);

	for (List<NodeImpl*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i) {
		for (uint32_t j = 0; j < (*i)->num_ports(); ++j) {
			PortImpl* const port = (*i)->port_impl(j);
			if (port->is_input() && dynamic_cast<InputPort*>(port)->direct_connect())
				port->setup_buffers(bufs, port->poly());
			port->connect_buffers(context.offset());
		}
	}

	const bool polyphonic = parent_patch() && (poly == parent_patch()->internal_poly());
	for (List<PortImpl*>::iterator i = _output_ports.begin(); i != _output_ports.end(); ++i)
		(*i)->setup_buffers(bufs, polyphonic ? poly : 1);

	_internal_poly = poly;

	return true;
}
Пример #7
0
unsigned
PreProcessor::process(ProcessContext& context, PostProcessor& dest, size_t limit)
{
	Event* const head = _head.load();
	if (!head) {
		return 0;
	}

	size_t n_processed = 0;
	Event* ev          = head;
	Event* last        = ev;
	while (ev && ev->is_prepared() && ev->time() < context.end()) {
		if (ev->time() < context.start()) {
			// Didn't get around to executing in time, oh well...
			ev->set_time(context.start());
		}
		ev->execute(context);
		last = ev;
		ev   = ev->next();
		++n_processed;
		if (limit && n_processed >= limit) {
			break;
		}
	}

	if (n_processed > 0) {
		Event* next = (Event*)last->next();
		last->next(NULL);
		dest.append(context, head, last);

		// Since _head was not NULL, we know it hasn't been changed since
		_head = next;

		/* If next is NULL, then _tail may now be invalid.  However, it would cause
		   a race to reset _tail here.  Instead, append() checks only _head for
		   emptiness, and resets the tail appropriately. */
	}

	return n_processed;
}
Пример #8
0
void MD5::processStream (InputStream& input, int64 numBytesToRead)
{
    ProcessContext context;

    if (numBytesToRead < 0)
        numBytesToRead = std::numeric_limits<int64>::max();

    while (numBytesToRead > 0)
    {
        uint8 tempBuffer [512];
        const int bytesRead = input.read (tempBuffer, (int) jmin (numBytesToRead, (int64) sizeof (tempBuffer)));

        if (bytesRead <= 0)
            break;

        numBytesToRead -= bytesRead;

        context.processBlock (tempBuffer, bytesRead);
    }

    context.finish (result);
}
Пример #9
0
void
TimeNode::run(ProcessContext& context)
{
	BufferRef          buf = _notify_port->buffer(0);
	LV2_Atom_Sequence* seq = buf->get<LV2_Atom_Sequence>();

	// Initialise output to the empty sequence
	seq->atom.type = _notify_port->bufs().uris().atom_Sequence;
	seq->atom.size = sizeof(LV2_Atom_Sequence_Body);
	seq->body.unit = 0;
	seq->body.pad  = 0;

	// Ask the driver to append any time events for this cycle
	context.engine().driver()->append_time_events(
		context, *_notify_port->buffer(0));
}
Пример #10
0
void
JackDriver::pre_process_port(ProcessContext& context, EnginePort* port)
{
	const SampleCount nframes    = context.nframes();
	jack_port_t*      jack_port  = (jack_port_t*)port->handle();
	PortImpl*         graph_port = port->graph_port();
	void*             buffer     = jack_port_get_buffer(jack_port, nframes);

	port->set_buffer(buffer);

	if (!graph_port->is_input()) {
		graph_port->buffer(0)->clear();
		return;
	}

	if (graph_port->is_a(PortType::AUDIO)) {
		Buffer* graph_buf = graph_port->buffer(0).get();
		memcpy(graph_buf->samples(), buffer, nframes * sizeof(float));

	} else if (graph_port->buffer_type() == graph_port->bufs().uris().atom_Sequence) {
		Buffer* graph_buf = (Buffer*)graph_port->buffer(0).get();

		const jack_nframes_t event_count = jack_midi_get_event_count(buffer);

		graph_buf->prepare_write(context);

		// Copy events from Jack port buffer into graph port buffer
		for (jack_nframes_t i = 0; i < event_count; ++i) {
			jack_midi_event_t ev;
			jack_midi_event_get(&ev, buffer, i);

			if (!graph_buf->append_event(
				    ev.time, ev.size, _midi_event_type, ev.buffer)) {
				_engine.log().warn("Failed to write to MIDI buffer, events lost!\n");
			}
		}
	}
}
Пример #11
0
void
DelayNode::run(ProcessContext& context)
{
	Buffer* const delay_buf = _delay_port->buffer(0).get();
	Buffer* const in_buf    = _in_port->buffer(0).get();
	Buffer* const out_buf   = _out_port->buffer(0).get();

	DelayNode* plugin_data = this;

	const float* const in            = in_buf->samples();
	float* const       out           = out_buf->samples();
	const float        delay_time    = delay_buf->samples()[0];
	const uint32_t     buffer_mask   = plugin_data->_buffer_mask;
	const SampleRate   sample_rate   = context.engine().driver()->sample_rate();
	float              delay_samples = plugin_data->_delay_samples;
	int64_t            write_phase   = plugin_data->_write_phase;
	const uint32_t     sample_count  = context.nframes();

	if (write_phase == 0) {
		_last_delay_time = delay_time;
		_delay_samples   = delay_samples = CALC_DELAY(delay_time);
	}

	if (delay_time == _last_delay_time) {
		const int64_t idelay_samples = (int64_t)delay_samples;
		const float   frac           = delay_samples - idelay_samples;

		for (uint32_t i = 0; i < sample_count; i++) {
			int64_t read_phase = write_phase - (int64_t)delay_samples;
			const float read = cube_interp(frac,
			                               buffer_at(read_phase - 1),
			                               buffer_at(read_phase),
			                               buffer_at(read_phase + 1),
			                               buffer_at(read_phase + 2));
			buffer_at(write_phase++) = in[i];
			out[i] = read;
		}
	} else {
		const float next_delay_samples  = CALC_DELAY(delay_time);
		const float delay_samples_slope = (next_delay_samples - delay_samples) / sample_count;

		for (uint32_t i = 0; i < sample_count; i++) {
			delay_samples += delay_samples_slope;
			write_phase++;
			const int64_t read_phase     = write_phase - (int64_t)delay_samples;
			const int64_t idelay_samples = (int64_t)delay_samples;
			const float   frac           = delay_samples - idelay_samples;
			const float   read           = cube_interp(frac,
			                                           buffer_at(read_phase - 1),
			                                           buffer_at(read_phase),
			                                           buffer_at(read_phase + 1),
			                                           buffer_at(read_phase + 2));
			buffer_at(write_phase) = in[i];
			out[i] = read;
		}

		_last_delay_time = delay_time;
		_delay_samples   = delay_samples;
	}

	_write_phase = write_phase;
}
Пример #12
0
MD5::MD5 (const void* data, const size_t numBytes)
{
    ProcessContext context;
    context.processBlock (data, numBytes);
    context.finish (result);
}
Пример #13
0
//==============================================================================
MD5::MD5 (const MemoryBlock& data)
{
    ProcessContext context;
    context.processBlock (data.getData(), data.getSize());
    context.finish (result);
}
Пример #14
0
void
DelayNode::process(ProcessContext& context)
{
	AudioBuffer* const delay_buf = (AudioBuffer*)_delay_port->buffer(0).get();
	AudioBuffer* const in_buf    = (AudioBuffer*)_in_port->buffer(0).get();
	AudioBuffer* const out_buf   = (AudioBuffer*)_out_port->buffer(0).get();

	NodeImpl::pre_process(context);

	DelayNode* plugin_data = this;

	const float* const in            = in_buf->data();
	float* const       out           = out_buf->data();
	const float        delay_time    = delay_buf->data()[0];
	const uint32_t     buffer_mask   = plugin_data->_buffer_mask;
	const unsigned int sample_rate   = plugin_data->_srate;
	float              delay_samples = plugin_data->_delay_samples;
	long               write_phase   = plugin_data->_write_phase;
	const uint32_t     sample_count  = context.nframes();

	if (write_phase == 0) {
		_last_delay_time = delay_time;
		_delay_samples   = delay_samples = CALC_DELAY(delay_time);
	}

	if (delay_time == _last_delay_time) {
		const long  idelay_samples = (long)delay_samples;
		const float frac           = delay_samples - idelay_samples;

		for (uint32_t i = 0; i < sample_count; i++) {
			long read_phase = write_phase - (long)delay_samples;
			const float read = cube_interp(frac,
					buffer_at(read_phase - 1),
					buffer_at(read_phase),
					buffer_at(read_phase + 1),
					buffer_at(read_phase + 2));
			buffer_at(write_phase++) = in[i];
			out[i] = read;
		}
	} else {
		const float next_delay_samples  = CALC_DELAY(delay_time);
		const float delay_samples_slope = (next_delay_samples - delay_samples) / sample_count;

		for (uint32_t i = 0; i < sample_count; i++) {
			delay_samples += delay_samples_slope;
			write_phase++;
			const long  read_phase     = write_phase - (long)delay_samples;
			const long  idelay_samples = (long)delay_samples;
			const float frac           = delay_samples - idelay_samples;
			const float read           = cube_interp(frac,
					buffer_at(read_phase - 1),
					buffer_at(read_phase),
					buffer_at(read_phase + 1),
					buffer_at(read_phase + 2));
			buffer_at(write_phase) = in[i];
			out[i] = read;
		}

		_last_delay_time = delay_time;
		_delay_samples   = delay_samples;
	}

	_write_phase = write_phase;

	NodeImpl::post_process(context);
}
Пример #15
0
 /** Signal the end of a cycle that has produced messages.
  * AUDIO THREAD ONLY.
  */
 inline void signal(ProcessContext& context) {
     ThreadManager::assert_thread(THREAD_PROCESS);
     const Request cycle_end_request(context.end(), NULL);
     _requests.write(sizeof(Request), &cycle_end_request);
     _sem.post();
 }
Пример #16
0
void
PatchImpl::process_parallel(ProcessContext& context)
{
	size_t n_slaves = context.slaves().size();

	CompiledPatch* const cp = _compiled_patch;

	/* Start p-1 slaves */

	if (n_slaves >= cp->size())
		n_slaves = cp->size()-1;

	if (n_slaves > 0) {
		for (size_t i = 0; i < cp->size(); ++i)
			(*cp)[i].node()->reset_input_ready();

		for (size_t i = 0; i < n_slaves; ++i)
			context.slaves()[i]->whip(cp, i+1, context);
	}

	/* Process ourself until everything is done
	 * This is analogous to ProcessSlave::_whipped(), but this is the master
	 * (i.e. what the main Jack process thread calls).  Where ProcessSlave
	 * waits on input, this just skips the node and tries the next, to avoid
	 * waiting in the Jack thread which pisses Jack off.
	 */

	size_t index        = 0;
	size_t num_finished = 0; // Number of consecutive finished nodes hit

	while (num_finished < cp->size()) {
		CompiledNode& n = (*cp)[index];

		if (n.node()->process_lock()) {
			if (n.node()->n_inputs_ready() == n.n_providers()) {
				n.node()->process(context);

				/* Signal dependants their input is ready */
				for (uint32_t i = 0; i < n.dependants().size(); ++i)
					n.dependants()[i]->signal_input_ready();

				++num_finished;
			} else {
				n.node()->process_unlock();
				num_finished = 0;
			}
		} else {
			if (n.node()->n_inputs_ready() == n.n_providers())
				++num_finished;
			else
				num_finished = 0;
		}

		index = (index + 1) % cp->size();
	}

	/* Tell slaves we're done in case we beat them, and pray they're
	 * really done by the start of next cycle.
	 * FIXME: This probably breaks (race) at extremely small nframes where
	 * ingen is the majority of the DSP load.
	 */
	for (uint32_t i = 0; i < n_slaves; ++i)
		context.slaves()[i]->finish();
}