| Hello everybody,
here is the code of a new UG for variable pitch
reading in a soundfile.
the sintax is almost the same as soundin:
a1 soundin2 ifilcod, iskptim, iformat, kfrqratio
a1, a2 soundin2 ifilcod, iskptim, iformat, kfrqratio
the new parameter kfrqratio is a multiplier factor and
must be > 0. This allows transposition and continuous modulation
of pitch. Note that the parameters iskiptim and iformat are
not optional now. Also note that this new unit only supports mono and
stereo 16bit integer audio files.
Known bugs:
-Do not use high transposition ratios (8 or 16) with low krate
(or high ksmps values as 100 or 50) otherwise the sound flow
could be broken.
-When the end of input soundfile is reached, some samples could be
lacking
in the output file.
this is the source:
////////////////// WARNING! in this source I often used the c++
////////////////// line comment sintax ( // comment ).
////////////////// Replace with standard c comment ( /* comment */ )
////////////////// if necessary
////////////////// In the SOUNDIO.H file
////////////////// you must REPLACE the old SOUNDIN structure
////////////////// as follows:
////////////////// (this change will not affect the normal behaviour
////////////////// of the old soundin unit)
typedef struct {
OPDS h;
float *r1, *r2, *r3, *r4, *ifilno, *iskptim, *iformat;
/* #ifdef GAB_RT */
float *kfrqratio; //GAB new parameter
// work variables GAB
double phase_gab; // hidden work variables
double fl_buf;
int base_sample_gab;
int initflag_gab;
/* #endif */
short format, channel, nchnls, sampframsiz, filetyp, analonly,
endfile;
long sr, audrem, framesrem, getframes; /* bytes, frames, frames */
AIFFDAT *aiffdata;
void (*bytrev)();
FDCH fdch;
char *inbufp, *bufend;
char inbuf[SNDINBUFSIZ*4]; //gab
} SOUNDIN;
/////////////////
///////////////// in the SOUNDIN.C file you must ADD the following
///////////////// functions:
/////////////////
void soundin2(SOUNDIN *p) //see SOUNDIO.H for GAB modification of type
SOUNDIN
{
/* Warning! use low k rate if tranpose factor is high:
for example, don't use ksmps > 5 if transpose factor is 16 */
short nsmps;
float *r1, *r2, *r3, *r4;
int chnsout, n, ntogo;
float ratio;
long base;
double *phase;
double *fl_buf;
double phase_diff;
base = p->base_sample_gab;
phase = &(p->phase_gab);
ratio = *(p->kfrqratio) * (p->sr/esr);
fl_buf = &(p->fl_buf);
r1 = p->r1; r2 = p->r2; r3 = p->r3; r4 = p->r4;
chnsout = p->OUTOCOUNT;
ntogo = ksmps;
if (p->endfile) goto filend;
nsmps = (p->bufend - p->inbufp) / p->sampframsiz;
if (nsmps > ksmps) nsmps = ksmps;
ntogo -= nsmps;
if (p->initflag_gab) {
size_t frame_size;
p->initflag_gab =0;
if (chnsout == 1) frame_size = sizeof(short);
else frame_size = sizeof(long);
lseek(p->fdch.fd, (long) *phase * frame_size , SEEK_SET );
if ((n = sreadin(p->fdch.fd,p->inbuf,SNDINBUFSIZ * 4,p)) == 0) {
p->endfile = 1;
if (ntogo) goto filend;
else return;
}
p->bufend = p->inbuf + n + SNDINBUFSIZ/32 ;
if (ntogo > 0) {
if ((nsmps = n / p->sampframsiz) > ntogo) nsmps = ntogo;
ntogo -= nsmps;
goto shorts;
}
}
switch (p->format) {
case AE_SHORT:
shorts:
switch(chnsout) {
case 1:
{
register short *base_addr;
register short *inbufp = (short *)p->inbufp;
base_addr = inbufp;
*fl_buf -= (long) *fl_buf;
do {
phase_diff = *phase - (long) *phase;
*r1++ = (float) *inbufp + (float) ( *(inbufp+1) -
*inbufp) * phase_diff; //gab
//*r1++ = (float) *inbufp;
*phase += ratio;
*fl_buf += ratio;
inbufp = base_addr + (long) *fl_buf;
} while (--nsmps);
if (inbufp >= ((short *)p->bufend)- SNDINBUFSIZ/32) {
lseek(p->fdch.fd, (long) *phase * sizeof(short), SEEK_SET
);
if ((n = sreadin(p->fdch.fd,p->inbuf,SNDINBUFSIZ * 4,p)) ==
0) {
p->endfile = 1;
if (ntogo) goto filend;
else return;
}
inbufp = (short *) p->inbuf;
p->bufend = p->inbuf + n + SNDINBUFSIZ/32 ;
if (ntogo > 0) {
if ((nsmps = n / p->sampframsiz) > ntogo)
nsmps = ntogo;
ntogo -= nsmps;
goto shorts;
}
}
p->inbufp = (char *) inbufp;
}
break;
case 2:
{
register long *base_addr;
register long *inbufp = (long *)p->inbufp;
base_addr = inbufp;
*fl_buf -= (long) *fl_buf;
do {
register short left,right, left1, right1;
phase_diff = *phase - (long) *phase;
left = (short) (*inbufp >> 16);
right =(short) ( *inbufp & 0xffff);
left1 = (short) (*(inbufp+1)>> 16);
right1 =(short) ( *(inbufp+1) & 0xffff);
*r1++ = (float) left + (float) ( left1 - left) *
phase_diff;
*r2++ = (float) right + (float) ( right1 - right) *
phase_diff;
*phase += ratio;
*fl_buf += ratio;
inbufp = base_addr + (long) *fl_buf;
} while (--nsmps);
if (inbufp >= ((long *)p->bufend)- SNDINBUFSIZ/32 ) {
lseek(p->fdch.fd, (long) *phase * sizeof(long) ,
SEEK_SET );
if ((n = sreadin(p->fdch.fd,p->inbuf,SNDINBUFSIZ * 4,p)) ==
0) {
p->endfile = 1;
if (ntogo) goto filend;
else return;
}
inbufp = (long *) p->inbuf;
p->bufend = p->inbuf + n + SNDINBUFSIZ/32;
if (ntogo > 0) {
if ((nsmps = n / p->sampframsiz) > ntogo)
nsmps = ntogo;
ntogo -= nsmps;
goto shorts;
}
}
p->inbufp = (char *) inbufp;
}
break;
default:
dies("soundin2 of %s not implemented",
getstrformat((int)p->format));
}
break;
default:
dies("soundin2 of %s not implemented",
getstrformat((int)p->format));
}
return;
filend:
nsmps = ntogo;
switch(chnsout) { /* if past end of file, */
case 1:
do *r1++ = fzero; /* move in zeros */
while (--nsmps);
break;
case 2:
do {
*r1++ = fzero;
*r2++ = fzero;
} while (--nsmps);
break;
}
}
//////////////// At the beginning of the ENTRY.C file you must add
//////////////// the following function declarations.....
void sndin2set(void*), soundin2(void*); //GAB
//////////////// ..... and the following line in the OENTRY opcodlst[]
//////////////// structure array declaration.
{ "soundin2",S(SOUNDIN), 5, "mmmm", "Sook", sndin2set,NULL,
soundin2 } //GAB
//////////////// That's all .... and good luck!
Gabriel Maldonado
|