예제 #1
0
파일: jack.c 프로젝트: disabled/phasex-dev
/*****************************************************************************
 *
 * PROCESS_BUFFER()
 *
 * callback for jack to read audio data from ringbuffer
 * jack uses a realtime priority thread for this
 *
 *****************************************************************************/
int 
process_buffer(jack_nframes_t nframes, void *arg) {
    jack_default_audio_sample_t *in1;
    jack_default_audio_sample_t *in2;
    jack_default_audio_sample_t *out1;
    jack_default_audio_sample_t *out2;
    int				portion1;
    int				portion2;
    int             j, osc, lfo;

    /* Get the input and output buffers for audio data */
    in1  = jack_port_get_buffer (input_port1,  nframes);
    in2  = jack_port_get_buffer (input_port2,  nframes);
    out1 = jack_port_get_buffer (output_port1, nframes);
    out2 = jack_port_get_buffer (output_port2, nframes);

    /* check for jack not running or global shutdown so we don't get hung on mutex */
    if (!jack_running || shutdown) {
	return 0;
    }

    /* copy circular buffers and update index */
    /* WARNING:  needs to handle circular buffer properly */
    if ((buffer_read_index + nframes) > buffer_size) {
	portion1 = buffer_size - buffer_read_index;
	portion2 = nframes - portion1;
	memcpy (&(input_buffer1[buffer_read_index]), in1,   sizeof (jack_default_audio_sample_t) * portion1);
	memcpy (&(input_buffer2[buffer_read_index]), in2,   sizeof (jack_default_audio_sample_t) * portion1);
	memcpy (input_buffer1, &(in1[portion1]), sizeof (jack_default_audio_sample_t) * portion2);
	memcpy (input_buffer2, &(in2[portion1]), sizeof (jack_default_audio_sample_t) * portion2);

	memcpy (out1, &(output_buffer1[buffer_read_index]), sizeof (jack_default_audio_sample_t) * portion1);
	memcpy (out2, &(output_buffer2[buffer_read_index]), sizeof (jack_default_audio_sample_t) * portion1);
	memcpy (&(out1[portion1]), output_buffer1, sizeof (jack_default_audio_sample_t) * portion2);
	memcpy (&(out2[portion1]), output_buffer2, sizeof (jack_default_audio_sample_t) * portion2);
    }
    else {
	memcpy (&(input_buffer1[buffer_read_index]), in1,   sizeof (jack_default_audio_sample_t) * nframes);
	memcpy (&(input_buffer2[buffer_read_index]), in2,   sizeof (jack_default_audio_sample_t) * nframes);
	memcpy (out1, &(output_buffer1[buffer_read_index]), sizeof (jack_default_audio_sample_t) * nframes);
	memcpy (out2, &(output_buffer2[buffer_read_index]), sizeof (jack_default_audio_sample_t) * nframes);
    }
    buffer_read_index += nframes;
    buffer_read_index %= buffer_size;

    /* Update buffer full and buffer needed counters */
    buffer_full   -= nframes;
    
    if(setting_jack_transport_mode)
    {
    /* jack transport sync */
    jack_state = jack_transport_query (client, &jack_pos);
    /* reinit sync vars if transport is just started */
    if((jack_prev_state == JackTransportStopped) && (jack_state == JackTransportStarting))
    {
        #ifdef EXTRA_DEBUG
        if (debug)
	    {
	        fprintf (stderr, "Starting sync.\n");
        }
        #endif
        need_resync = 1;
    }
    if(jack_state == JackTransportRolling)
    {
        if(need_resync)
        {
            prev_frame = jack_pos.frame - nframes;
            frames_per_beat = sample_rate / global.bps;
            frames_per_tick = sample_rate / (jack_pos.ticks_per_beat * global.bps);
            current_frame = 0;
            need_resync = 0;
        }
    
        /* Handle BPM change */
        if(jack_pos.beats_per_minute && (global.bps != jack_pos.beats_per_minute / 60.0))
        {
            param[0].cc_val[program_number] = jack_pos.beats_per_minute - 64;
		    param[0].callback (main_window, (gpointer)(&(param[0])));
	    }
	    
	    /* frame-based sync */
	    current_frame = (jack_pos.frame - prev_frame);
	    prev_frame = jack_pos.frame;
	    
	    if(current_frame != nframes)
	    {
	        /* whoooaaaa, we're traveling through time! */
	        phase_correction = current_frame - nframes;
	    }
	    
	    /* do the actual sync */
	    if(phase_correction && (setting_jack_transport_mode == JACK_TRANSPORT_TNP))
	    {
	        #ifdef EXTRA_DEBUG
	        if (debug)
	        {
	            fprintf (stderr, "Out of sync. Phase correction:  %d\n", phase_correction);
            }
            #endif
            
	        part.delay_write_index += phase_correction;
	        while(part.delay_write_index < 0.0)
		        part.delay_write_index += part.delay_bufsize;
	        while(part.delay_write_index >= part.delay_bufsize)
		        part.delay_write_index -= part.delay_bufsize;
	    
	        part.chorus_lfo_index_a += phase_correction * part.chorus_lfo_adjust;
	        while(part.chorus_lfo_index_a < 0.0)
		        part.chorus_lfo_index_a += F_WAVEFORM_SIZE;
	        while(part.chorus_lfo_index_a >= F_WAVEFORM_SIZE)
		        part.chorus_lfo_index_a -= F_WAVEFORM_SIZE;

		    part.chorus_lfo_index_b = part.chorus_lfo_index_a + (F_WAVEFORM_SIZE * 0.25);
	        while(part.chorus_lfo_index_b < 0.0)
		        part.chorus_lfo_index_b += F_WAVEFORM_SIZE;
	        while(part.chorus_lfo_index_b >= F_WAVEFORM_SIZE)
		        part.chorus_lfo_index_b -= F_WAVEFORM_SIZE;

		    part.chorus_lfo_index_c = part.chorus_lfo_index_a + (F_WAVEFORM_SIZE * 0.5);
	        while(part.chorus_lfo_index_c < 0.0)
		        part.chorus_lfo_index_c += F_WAVEFORM_SIZE;
	        while(part.chorus_lfo_index_c >= F_WAVEFORM_SIZE)
		        part.chorus_lfo_index_c -= F_WAVEFORM_SIZE;

		    part.chorus_lfo_index_d = part.chorus_lfo_index_a + (F_WAVEFORM_SIZE * 0.75);
	        while(part.chorus_lfo_index_d < 0.0)
		        part.chorus_lfo_index_d += F_WAVEFORM_SIZE;
	        while(part.chorus_lfo_index_d >= F_WAVEFORM_SIZE)
		        part.chorus_lfo_index_d -= F_WAVEFORM_SIZE;
	    
	        for (osc = 0; osc < NUM_OSCS; osc++) {
				for (j = 0; j < setting_polyphony; j++) {
				    if (patch->osc_freq_base[osc] >= FREQ_BASE_TEMPO) 
				    {
				        switch (patch->freq_mod_type[osc]) {
		                case MOD_TYPE_LFO:
			            tmp_1 = part.lfo_out[patch->freq_lfo[osc]];
			            break;
		                case MOD_TYPE_OSC:
			            tmp_1 = ( voice[j].osc_out1[part.osc_freq_mod[osc]] + voice[j].osc_out2[part.osc_freq_mod[osc]] ) * 0.5;
			            break;
		                case MOD_TYPE_VELOCITY:
			            tmp_1 = voice[j].velocity_coef_linear;
			            break;
		                default:
			            tmp_1 = 0.0;
			            break;
		                }
		                
				        voice[j].index[osc] += phase_correction
				            * halfsteps_to_freq_mult ( ( tmp_1
					        * patch->freq_lfo_amount[osc] )
							   + part.osc_pitch_bend[osc]
							   + patch->osc_transpose[osc] )
			                * voice[j].osc_freq[osc] * wave_period;
				        
				        while (voice[j].index[osc] < 0.0)
			                voice[j].index[osc] += F_WAVEFORM_SIZE;
		                while (voice[j].index[osc] >= F_WAVEFORM_SIZE)
			                voice[j].index[osc] -= F_WAVEFORM_SIZE;
				    }
				}
			}
			for (lfo = 0; lfo < NUM_LFOS; lfo++) {
			    if (patch->lfo_freq_base[lfo] >= FREQ_BASE_TEMPO) 
			    {
				    part.lfo_index[lfo] += phase_correction
				        * part.lfo_freq[lfo]
		                * halfsteps_to_freq_mult (patch->lfo_transpose[lfo] + part.lfo_pitch_bend[lfo])
		                * wave_period;
				    
				    while (part.lfo_index[lfo] < 0.0)
		                part.lfo_index[lfo] += F_WAVEFORM_SIZE;
		            while (part.lfo_index[lfo] >= F_WAVEFORM_SIZE)
		                part.lfo_index[lfo] -= F_WAVEFORM_SIZE;
				}
			}
			phase_correction = 0;
	    }
    }
    else if ((jack_state == JackTransportStopped) && (jack_prev_state == JackTransportRolling))
    {        
        /* send NOTE_OFFs on transport stop */
        engine_notes_off();
    }
    
    jack_prev_state = jack_state;
    } /* if(setting_jack_transport) */

    /* Signal the engine that there's space again */
    if (pthread_mutex_trylock (&buffer_mutex) == 0) {
	pthread_cond_broadcast (&buffer_has_space);
	pthread_mutex_unlock (&buffer_mutex);
    }

    return 0;
}
예제 #2
0
/*****************************************************************************
 * process_phase_sync()
 *
 * Process a phase sync internal MIDI message.  Currently used for syncing
 * JACK Transport, this function performs phase correction for a given voice.
 *****************************************************************************/
void
process_phase_sync(MIDI_EVENT *event, unsigned int part_num)
{
	PART            *part              = get_part(part_num);
	PATCH_STATE     *state             = get_active_state(part_num);
	DELAY           *delay             = get_delay(part_num);
	CHORUS          *chorus            = get_chorus(part_num);
	VOICE           *voice;
	int             voice_num;
	int             osc;
	int             lfo;
	int             phase_correction   = event->value;
	sample_t        f_phase_correction = (sample_t) phase_correction;
	sample_t        tmp_1;

	delay->write_index += phase_correction;
	while (delay->write_index < 0.0) {
		delay->write_index += delay->bufsize;
	}
	while (delay->write_index >= delay->bufsize) {
		delay->write_index -= delay->bufsize;
	}

	chorus->lfo_index_a += f_phase_correction * chorus->lfo_adjust;
	while (chorus->lfo_index_a < 0.0) {
		chorus->lfo_index_a += F_WAVEFORM_SIZE;
	}
	while (chorus->lfo_index_a >= F_WAVEFORM_SIZE) {
		chorus->lfo_index_a -= F_WAVEFORM_SIZE;
	}

	chorus->lfo_index_b = chorus->lfo_index_a + (F_WAVEFORM_SIZE * 0.25);
	while (chorus->lfo_index_b < 0.0) {
		chorus->lfo_index_b += F_WAVEFORM_SIZE;
	}
	while (chorus->lfo_index_b >= F_WAVEFORM_SIZE) {
		chorus->lfo_index_b -= F_WAVEFORM_SIZE;
	}

	chorus->lfo_index_c = chorus->lfo_index_a + (F_WAVEFORM_SIZE * 0.5);
	while (chorus->lfo_index_c < 0.0) {
		chorus->lfo_index_c += F_WAVEFORM_SIZE;
	}
	while (chorus->lfo_index_c >= F_WAVEFORM_SIZE) {
		chorus->lfo_index_c -= F_WAVEFORM_SIZE;
	}

	chorus->lfo_index_d = chorus->lfo_index_a + (F_WAVEFORM_SIZE * 0.75);
	while (chorus->lfo_index_d < 0.0) {
		chorus->lfo_index_d += F_WAVEFORM_SIZE;
	}
	while (chorus->lfo_index_d >= F_WAVEFORM_SIZE) {
		chorus->lfo_index_d -= F_WAVEFORM_SIZE;
	}

	for (voice_num = 0; voice_num < setting_polyphony; voice_num++) {
		voice = get_voice(part_num, voice_num);
		for (osc = 0; osc < NUM_OSCS; osc++) {
			if (state->osc_freq_base[osc] >= FREQ_BASE_TEMPO) {
				switch (state->freq_mod_type[osc]) {
				case MOD_TYPE_LFO:
					tmp_1 = part->lfo_out[state->freq_lfo[osc]];
					break;
				case MOD_TYPE_OSC:
					tmp_1 = (voice->osc_out1[part->osc_freq_mod[osc]] +
					         voice->osc_out2[part->osc_freq_mod[osc]]) * 0.5;
					break;
				case MOD_TYPE_VELOCITY:
					tmp_1 = voice->velocity_coef_linear;
					break;
				default:
					tmp_1 = 0.0;
					break;
				}

				voice->index[osc] +=
					f_phase_correction *
					halfsteps_to_freq_mult((tmp_1 *
					                        state->freq_lfo_amount[osc]) +
					                       part->osc_pitch_bend[osc] +
					                       state->osc_transpose[osc] +
					                       state->voice_osc_tune[voice->id] ) *
					voice->osc_freq[osc] * wave_period;

				while (voice->index[osc] < 0.0) {
					voice->index[osc] += F_WAVEFORM_SIZE;
				}
				while (voice->index[osc] >= F_WAVEFORM_SIZE) {
					voice->index[osc] -= F_WAVEFORM_SIZE;
				}
			}
		}
	}
	for (lfo = 0; lfo < NUM_LFOS; lfo++) {
		if (state->lfo_freq_base[lfo] >= FREQ_BASE_TEMPO) {
			part->lfo_index[lfo] +=
				f_phase_correction *
				part->lfo_freq[lfo] *
				halfsteps_to_freq_mult(state->lfo_transpose[lfo] + part->lfo_pitch_bend[lfo]) *
				wave_period;

			while (part->lfo_index[lfo] < 0.0) {
				part->lfo_index[lfo] += F_WAVEFORM_SIZE;
			}
			while (part->lfo_index[lfo] >= F_WAVEFORM_SIZE) {
				part->lfo_index[lfo] -= F_WAVEFORM_SIZE;
			}
		}
	}
}