예제 #1
0
static int snd_seq_gf1_get(void *private_data, snd_seq_kinstr_t *instr,
			   char *instr_data, long len, int atomic, int cmd)
{
	snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
	gf1_instrument_t *ip;
	gf1_xinstrument_t ix;
	
	if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
		return -EINVAL;
	if (len < sizeof(ix))
		return -ENOMEM;
	memset(&ix, 0, sizeof(ix));
	ip = (gf1_instrument_t *)KINSTR_DATA(instr);
	ix.stype = GF1_STRU_INSTR;
	ix.exclusion = cpu_to_le16(ip->exclusion);
	ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
	ix.effect1 = cpu_to_le16(ip->effect1);
	ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
	ix.effect2 = ip->effect2;
	ix.effect2_depth = ip->effect2_depth;
	if (copy_to_user(instr_data, &ix, sizeof(ix)))
		return -EFAULT;
	instr_data += sizeof(ix);
	len -= sizeof(ix);
	return snd_seq_gf1_copy_wave_to_stream(ops,
					       ip,
					       &instr_data,
					       &len,
					       atomic);
}
예제 #2
0
static int snd_seq_iwffff_remove(void *private_data,
				 snd_seq_kinstr_t *instr,
                                 int atomic)
{
	snd_iwffff_ops_t *ops = (snd_iwffff_ops_t *)private_data;
	iwffff_instrument_t *ip;

	ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
	snd_seq_iwffff_instr_free(ops, ip, atomic);
	return 0;
}
예제 #3
0
static int snd_seq_gf1_put(void *private_data, snd_seq_kinstr_t *instr,
			   char *instr_data, long len, int atomic, int cmd)
{
	snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
	gf1_instrument_t *ip;
	gf1_xinstrument_t ix;
	int err, gfp_mask;

	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
		return -EINVAL;
	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
	/* copy instrument data */
	if (len < sizeof(ix))
		return -EINVAL;
	if (copy_from_user(&ix, instr_data, sizeof(ix)))
		return -EFAULT;
	if (ix.stype != GF1_STRU_INSTR)
		return -EINVAL;
	instr_data += sizeof(ix);
	len -= sizeof(ix);
	ip = (gf1_instrument_t *)KINSTR_DATA(instr);
	ip->exclusion = le16_to_cpu(ix.exclusion);
	ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
	ip->effect1 = ix.effect1;
	ip->effect1_depth = ix.effect1_depth;
	ip->effect2 = ix.effect2;
	ip->effect2_depth = ix.effect2_depth;
	/* copy layers */
	while (len > sizeof(__u32)) {
		__u32 stype;

		if (copy_from_user(&stype, instr_data, sizeof(stype)))
			return -EFAULT;
		if (stype != GF1_STRU_WAVE) {
			snd_seq_gf1_instr_free(ops, ip, atomic);
			return -EINVAL;
		}
		err = snd_seq_gf1_copy_wave_from_stream(ops,
							ip,
							&instr_data,
							&len,
							atomic);
		if (err < 0) {
			snd_seq_gf1_instr_free(ops, ip, atomic);
			return err;
		}
	}
	return 0;
}
예제 #4
0
static int snd_seq_gf1_get_size(void *private_data, snd_seq_kinstr_t *instr,
				long *size)
{
	long result;
	gf1_instrument_t *ip;
	gf1_wave_t *wp;

	*size = 0;
	ip = (gf1_instrument_t *)KINSTR_DATA(instr);
	result = sizeof(gf1_xinstrument_t);
	for (wp = ip->wave; wp; wp = wp->next) {
		result += sizeof(gf1_xwave_t);
		result += wp->size;
	}
	*size = result;
	return 0;
}
예제 #5
0
static int snd_seq_iwffff_get_size(void *private_data, snd_seq_kinstr_t *instr,
				   long *size)
{
	long result;
	iwffff_instrument_t *ip;
	iwffff_layer_t *lp;

	*size = 0;
	ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
	result = sizeof(iwffff_xinstrument_t);
	for (lp = ip->layer; lp; lp = lp->next) {
		result += sizeof(iwffff_xlayer_t);
		result += snd_seq_iwffff_env_size_in_stream(&lp->penv);
		result += snd_seq_iwffff_env_size_in_stream(&lp->venv);
		result += snd_seq_iwffff_wave_size_in_stream(lp);
	}
	*size = result;
	return 0;
}
예제 #6
0
static int snd_seq_fm_get(void *private_data, snd_seq_kinstr_t *instr,
			  char __user *instr_data, long len, int atomic,
			  int cmd)
{
	fm_instrument_t *ip;
	fm_xinstrument_t ix;
	int idx;
	
	if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
		return -EINVAL;
	if (len < (long)sizeof(ix))
		return -ENOMEM;
	memset(&ix, 0, sizeof(ix));
	ip = (fm_instrument_t *)KINSTR_DATA(instr);
	ix.stype = FM_STRU_INSTR;
	ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
	ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
	ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
	ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
	ix.type = ip->type;
	for (idx = 0; idx < 4; idx++) {
		ix.op[idx].am_vib = ip->op[idx].am_vib;
		ix.op[idx].ksl_level = ip->op[idx].ksl_level;
		ix.op[idx].attack_decay = ip->op[idx].attack_decay;
		ix.op[idx].sustain_release = ip->op[idx].sustain_release;
		ix.op[idx].wave_select = ip->op[idx].wave_select;
	}
	for (idx = 0; idx < 2; idx++) {
		ix.feedback_connection[idx] = ip->feedback_connection[idx];
	}
	if (copy_to_user(instr_data, &ix, sizeof(ix)))
		return -EFAULT;
	ix.echo_delay = ip->echo_delay;
	ix.echo_atten = ip->echo_atten;
	ix.chorus_spread = ip->chorus_spread;
	ix.trnsps = ip->trnsps;
	ix.fix_dur = ip->fix_dur;
	ix.modes = ip->modes;
	ix.fix_key = ip->fix_key;
	return 0;
}
예제 #7
0
static int snd_seq_fm_put(void *private_data, struct snd_seq_kinstr *instr,
			  char __user *instr_data, long len, int atomic, int cmd)
{
	struct fm_instrument *ip;
	struct fm_xinstrument ix;
	int idx;

	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
		return -EINVAL;
	/* copy instrument data */
	if (len < (long)sizeof(ix))
		return -EINVAL;
	if (copy_from_user(&ix, instr_data, sizeof(ix)))
		return -EFAULT;
	if (ix.stype != FM_STRU_INSTR)
		return -EINVAL;
	ip = (struct fm_instrument *)KINSTR_DATA(instr);
	ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
	ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
	ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
	ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
	ip->type = ix.type;
	for (idx = 0; idx < 4; idx++) {
		ip->op[idx].am_vib = ix.op[idx].am_vib;
		ip->op[idx].ksl_level = ix.op[idx].ksl_level;
		ip->op[idx].attack_decay = ix.op[idx].attack_decay;
		ip->op[idx].sustain_release = ix.op[idx].sustain_release;
		ip->op[idx].wave_select = ix.op[idx].wave_select;
	}
	for (idx = 0; idx < 2; idx++) {
		ip->feedback_connection[idx] = ix.feedback_connection[idx];
	}
	ip->echo_delay = ix.echo_delay;
	ip->echo_atten = ix.echo_atten;
	ip->chorus_spread = ix.chorus_spread;
	ip->trnsps = ix.trnsps;
	ip->fix_dur = ix.fix_dur;
	ip->modes = ix.modes;
	ip->fix_key = ix.fix_key;
	return 0;
}
예제 #8
0
static void sample_start(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position)
{
	simple_instrument_t *simple;
	snd_seq_kinstr_t *instr;
	unsigned long flags;
	unsigned int loop_start, loop_end, sample_start, sample_end, start_offset;
	unsigned int value;
	unsigned int shift = 0;

	instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
	if (instr == NULL)
		return;
	voice->instr = instr->instr;	/* copy ID to speedup aliases */
	simple = KINSTR_DATA(instr);

	spin_lock_irqsave(&trident->reg_lock, flags);

	if (trident->device == TRIDENT_DEVICE_ID_SI7018)
		voice->GVSel = 1;	/* route to Wave volume */

	voice->CTRL = 0;
	voice->Alpha = 0;
	voice->FMS = 0;

	loop_start = simple->loop_start >> 4;
	loop_end = simple->loop_end >> 4;
	sample_start = (simple->start + position) >> 4;
	if( sample_start >= simple->size )
		sample_start = simple->start >> 4;
	sample_end = simple->size;
	start_offset = position >> 4;

	if (simple->format & SIMPLE_WAVE_16BIT) {
		voice->CTRL |= 8;
		shift++;
	}
	if (simple->format & SIMPLE_WAVE_STEREO) {
		voice->CTRL |= 4;
		shift++;
	}
	if (!(simple->format & SIMPLE_WAVE_UNSIGNED))
		voice->CTRL |= 2;

	voice->LBA = simple->address.memory;

	if (simple->format & SIMPLE_WAVE_LOOP) {
		voice->CTRL |= 1;
		voice->LBA += loop_start << shift;
		if( start_offset >= loop_start ) {
			voice->CSO = start_offset - loop_start;
			voice->negCSO = 0;
		} else {
			voice->CSO = loop_start - start_offset;
			voice->negCSO = 1;
		}
		voice->ESO = loop_end - loop_start - 1;
	} else {
		voice->LBA += start_offset << shift;
		voice->CSO = sample_start;
		voice->ESO = sample_end - 1;
		voice->negCSO = 0;
	}

	if (voice->flags & SNDRV_TRIDENT_VFLG_RUNNING) {
		snd_trident_stop_voice(trident, voice->number);
		voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
	}

	/* set CSO sign */
	value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));
	if( voice->negCSO ) {
		value |= 1 << (voice->number&31);
	} else {
		value &= ~(1 << (voice->number&31));
	}
	outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));

	voice->Attribute = 0;	
	snd_trident_write_voice_regs(trident, voice);
	snd_trident_start_voice(trident, voice->number);
	voice->flags |= SNDRV_TRIDENT_VFLG_RUNNING;
	spin_unlock_irqrestore(&trident->reg_lock, flags);
	snd_seq_instr_free_use(trident->synth.ilist, instr);
}
예제 #9
0
static int snd_seq_iwffff_get(void *private_data, snd_seq_kinstr_t *instr,
			      char __user *instr_data, long len, int atomic, int cmd)
{
	snd_iwffff_ops_t *ops = (snd_iwffff_ops_t *)private_data;
	iwffff_instrument_t *ip;
	iwffff_xinstrument_t ix;
	iwffff_layer_t *lp;
	iwffff_xlayer_t lx;
	char __user *layer_instr_data;
	int err;
	
	if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
		return -EINVAL;
	if (len < (long)sizeof(ix))
		return -ENOMEM;
	memset(&ix, 0, sizeof(ix));
	ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
	ix.stype = IWFFFF_STRU_INSTR;
	ix.exclusion = cpu_to_le16(ip->exclusion);
	ix.layer_type = cpu_to_le16(ip->layer_type);
	ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
	ix.effect1 = cpu_to_le16(ip->effect1);
	ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
	ix.effect2 = ip->effect2;
	ix.effect2_depth = ip->effect2_depth;
	if (copy_to_user(instr_data, &ix, sizeof(ix)))
		return -EFAULT;
	instr_data += sizeof(ix);
	len -= sizeof(ix);
	for (lp = ip->layer; lp; lp = lp->next) {
		if (len < (long)sizeof(lx))
			return -ENOMEM;
		memset(&lx, 0, sizeof(lx));
		lx.stype = IWFFFF_STRU_LAYER;
		lx.flags = lp->flags;
		lx.velocity_mode = lp->velocity_mode;
		lx.layer_event = lp->layer_event;
		lx.low_range = lp->low_range;
		lx.high_range = lp->high_range;
		lx.pan = lp->pan;
		lx.pan_freq_scale = lp->pan_freq_scale;
		lx.attenuation = lp->attenuation;
		snd_seq_iwffff_copy_lfo_to_stream(&lx.tremolo, &lp->tremolo);
		snd_seq_iwffff_copy_lfo_to_stream(&lx.vibrato, &lp->vibrato);
		layer_instr_data = instr_data;
		instr_data += sizeof(lx);
		len -= sizeof(lx);
		err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECP,
							lp,
							&lx.penv, &lp->penv,
						        &instr_data, &len);
		if (err < 0)
			return err;
		err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECV,
							lp,
							&lx.venv, &lp->venv,
						        &instr_data, &len);
		if (err < 0)
			return err;
		/* layer structure updating is now finished */
		if (copy_to_user(layer_instr_data, &lx, sizeof(lx)))
			return -EFAULT;
		err = snd_seq_iwffff_copy_wave_to_stream(ops,
							 lp,
							 &instr_data,
							 &len,
							 atomic);
		if (err < 0)
			return err;
	}
	return 0;
}
예제 #10
0
static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
			      char __user *instr_data, long len, int atomic,
			      int cmd)
{
	snd_iwffff_ops_t *ops = (snd_iwffff_ops_t *)private_data;
	iwffff_instrument_t *ip;
	iwffff_xinstrument_t ix;
	iwffff_layer_t *lp, *prev_lp;
	iwffff_xlayer_t lx;
	int err, gfp_mask;

	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
		return -EINVAL;
	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
	/* copy instrument data */
	if (len < (long)sizeof(ix))
		return -EINVAL;
	if (copy_from_user(&ix, instr_data, sizeof(ix)))
		return -EFAULT;
	if (ix.stype != IWFFFF_STRU_INSTR)
		return -EINVAL;
	instr_data += sizeof(ix);
	len -= sizeof(ix);
	ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
	ip->exclusion = le16_to_cpu(ix.exclusion);
	ip->layer_type = le16_to_cpu(ix.layer_type);
	ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
	ip->effect1 = ix.effect1;
	ip->effect1_depth = ix.effect1_depth;
	ip->effect2 = ix.effect2;
	ip->effect2_depth = ix.effect2_depth;
	/* copy layers */
	prev_lp = NULL;
	while (len > 0) {
		if (len < (long)sizeof(iwffff_xlayer_t)) {
			snd_seq_iwffff_instr_free(ops, ip, atomic);
			return -EINVAL;
		}
		if (copy_from_user(&lx, instr_data, sizeof(lx)))
			return -EFAULT;
		instr_data += sizeof(lx);
		len -= sizeof(lx);
		if (lx.stype != IWFFFF_STRU_LAYER) {
			snd_seq_iwffff_instr_free(ops, ip, atomic);
			return -EINVAL;
		}
		lp = kcalloc(1, sizeof(*lp), gfp_mask);
		if (lp == NULL) {
			snd_seq_iwffff_instr_free(ops, ip, atomic);
			return -ENOMEM;
		}
		if (prev_lp) {
			prev_lp->next = lp;
		} else {
			ip->layer = lp;
		}
		prev_lp = lp;
		lp->flags = lx.flags;
		lp->velocity_mode = lx.velocity_mode;
		lp->layer_event = lx.layer_event;
		lp->low_range = lx.low_range;
		lp->high_range = lx.high_range;
		lp->pan = lx.pan;
		lp->pan_freq_scale = lx.pan_freq_scale;
		lp->attenuation = lx.attenuation;
		snd_seq_iwffff_copy_lfo_from_stream(&lp->tremolo, &lx.tremolo);
		snd_seq_iwffff_copy_lfo_from_stream(&lp->vibrato, &lx.vibrato);
		lp->freq_scale = le16_to_cpu(lx.freq_scale);
		lp->freq_center = lx.freq_center;
		err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECP,
							  lp,
							  &lp->penv, &lx.penv,
						          &instr_data, &len,
						          gfp_mask);
		if (err < 0) {
			snd_seq_iwffff_instr_free(ops, ip, atomic);
			return err;
		}
		err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECV,
							  lp,
							  &lp->venv, &lx.venv,
						          &instr_data, &len,
						          gfp_mask);
		if (err < 0) {
			snd_seq_iwffff_instr_free(ops, ip, atomic);
			return err;
		}
		while (len > (long)sizeof(__u32)) {
			__u32 stype;

			if (copy_from_user(&stype, instr_data, sizeof(stype)))
				return -EFAULT;
			if (stype != IWFFFF_STRU_WAVE)
				break;
			err = snd_seq_iwffff_copy_wave_from_stream(ops,
								   lp,
							    	   &instr_data,
								   &len,
								   atomic);
			if (err < 0) {
				snd_seq_iwffff_instr_free(ops, ip, atomic);
				return err;
			}
		}
	}
	return 0;
}