/* * Audio support data for ISDN4Linux. * * Copyright Andreas Eversberg (jolly@eversberg.eu) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. *
*/
/****************** * copy tone data *
******************/
/* an sk_buff is generated from the number of samples needed. * the count will be changed and may begin from 0 each pattern period. * the clue is to precalculate the pointers and legths to use only one * memcpy per function call, or two memcpy if the tone sequence changes. * * pattern - the type of the pattern * count - the sample from the beginning of the pattern (phase) * len - the number of bytes * * return - the sk_buff with the sample * * if tones has finished (e.g. knocking tone), dsp->tones is turned off
*/ void dsp_tone_copy(struct dsp *dsp, u8 *data, int len)
{ int index, count, start, num; struct pattern *pat; struct dsp_tone *tone = &dsp->tone;
/* if we have no tone, we copy silence */ if (!tone->tone) {
memset(data, dsp_silence, len); return;
}
/* process pattern */
pat = (struct pattern *)tone->pattern; /* points to the current pattern */
index = tone->index; /* gives current sequence index */
count = tone->count; /* gives current sample */
/* copy sample */ while (len) { /* find sample to start with */ while (42) { /* wrap around */ if (!pat->seq[index]) {
count = 0;
index = 0;
} /* check if we are currently playing this tone */ if (count < pat->seq[index]) break; if (dsp_debug & DEBUG_DSP_TONE)
printk(KERN_DEBUG "%s: reaching next sequence " "(index=%d)\n", __func__, index);
count -= pat->seq[index];
index++;
} /* calculate start and number of samples */
start = count % (*(pat->siz[index]));
num = len; if (num + count > pat->seq[index])
num = pat->seq[index] - count; if (num + start > (*(pat->siz[index])))
num = (*(pat->siz[index])) - start; /* copy memory */
memcpy(data, pat->data[index] + start, num); /* reduce length */
data += num;
count += num;
len -= num;
}
tone->index = index;
tone->count = count;
/* return sk_buff */ return;
}
/******************************* * send HW message to hfc card *
*******************************/
/* unlocking is not required, because we don't expect a response */
nskb = _alloc_mISDN_skb(PH_CONTROL_REQ,
(len) ? HFC_SPL_LOOP_ON : HFC_SPL_LOOP_OFF, len, sample,
GFP_ATOMIC); if (nskb) { if (dsp->ch.peer) { if (dsp->ch.recv(dsp->ch.peer, nskb))
dev_kfree_skb(nskb);
} else
dev_kfree_skb(nskb);
}
}
index++; if (!pat->seq[index])
index = 0;
tone->index = index;
/* set next tone */ if (pat->data[index] == DATA_S)
dsp_tone_hw_message(dsp, NULL, 0); else
dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index])); /* set timer */
tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
add_timer(&tone->tl);
}
/******************** * set/release tone *
********************/
/* * tones are relaized by streaming or by special loop commands if supported * by hardware. when hardware is used, the patterns will be controlled by * timers.
*/ int
dsp_tone(struct dsp *dsp, int tone)
{ struct pattern *pat; int i; struct dsp_tone *tonet = &dsp->tone;
tonet->software = 0;
tonet->hardware = 0;
/* we turn off the tone */ if (!tone) { if (dsp->features.hfc_loops && timer_pending(&tonet->tl))
timer_delete(&tonet->tl); if (dsp->features.hfc_loops)
dsp_tone_hw_message(dsp, NULL, 0);
tonet->tone = 0; return 0;
}
pat = NULL;
i = 0; while (pattern[i].tone) { if (pattern[i].tone == tone) {
pat = &pattern[i]; break;
}
i++;
} if (!pat) {
printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone); return -EINVAL;
} if (dsp_debug & DEBUG_DSP_TONE)
printk(KERN_DEBUG "%s: now starting tone %d (index=%d)\n",
__func__, tone, 0);
tonet->tone = tone;
tonet->pattern = pat;
tonet->index = 0;
tonet->count = 0;
if (dsp->features.hfc_loops) {
tonet->hardware = 1; /* set first tone */
dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0])); /* set timer */ if (timer_pending(&tonet->tl))
timer_delete(&tonet->tl);
tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000;
add_timer(&tonet->tl);
} else {
tonet->software = 1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.