/* GETWSOV.C * The routine that implements the 'Get Wavesample Overview' message. ** NB: There are two versions of this routine. * * Copyright (C) 1991 by Andrew Arensburger. Permission is granted to * use, copy and/or distribute this file freely for non-commercial purposes, * as long as this notice remains intact. Any commercial use is prohibited * without express permission from the author. * * If you make any changes, fix bugs, etc., please send them to me that I * might coordinate fixes and improvements. */ #include #include "eps.h" #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif #ifndef MAX #define MAX(x,y) ((x)<(y)?(y):(x)) #endif /* GET_WSOV * Get an overview of the wavesample described in 'inst'. The result is, * roughly speaking, an array of 512 values, each of which contains the * highest sample value (in absolute value) of that particular 1/512th * of the portion of the wavesample contained between 'from' and 'to'. * The overview is returned in 'out'. * Returns 0 on no error, or a negative error code on error. * NB: This version of the routine is a hack: it performs all of the * comparisons manually. It gets all of the samples in the range, then * performs the comparisons itself on all of the data. */ int get_wsov(chan,inst,from,to,out) int chan; /* MIDI channel */ edit_spec *inst; /* Which wavesample? */ ulong from, to; /* Range */ short *out; /* Description will be put here */ { int i; ulong n; /* Sample counter */ int waiting; /* Are we waiting for the EPS to do things? */ ulong slice; /* Size of each slice of data */ short max; /* Local maxima */ slice = (to - from) >> 9; /* Range / 512 */ /* Send request for wavesample data */ send_head(chan); /* Send SysEx head */ mpu_sbyte(GET_WSDATA); /* Request wavesample data */ send12(inst->inst_num); /* Instrument number */ send12(inst->layer_num);/* Layer number */ send12(inst->ws_num); /* Wavesample number */ send_off(from); /* Beginning of range */ send_off(to); /* End of range */ send_tail(); /* Send SysEx tail */ if (timeout(SHORT_TIMEOUT)) return(-1); /* Short timeout occurred */ /* This loop is a bit tricky. The basic idea is that the EPS can * send out one of three responses at this point: ACK, WAIT, or * something else. * If it sends an ACK, then all is well, and we can go on to * receive the data. If it sends a something else, then there's * clearly an error, and we can abort with a clean conscience. * If it sends a WAIT, however, then we have to wait for up to * 30 seconds, during which time any of the above can happen, * including a second, third, etc. WAIT message. * If the EPS has sent a WAIT, it will send an ACK before * sending the data (but this was implied by the above para- * graphs). */ waiting = 1; while (waiting) { /* See which response the EPS sends, and react * accordingly. */ switch(recv_response(NULL)) { case ACK: /* Acknowledgement */ waiting = 0; /* Stop waiting */ break; case WAIT: /* Wait for up to 30 seconds */ send_response(chan, ACK); /* Okay, I'll wait */ /* Wait for a timeout */ if (timeout(LONG_TIMEOUT)) return(-3); /* 30-sec timeout * has occurred */ break; default: /* Something's wrong */ wait(BREATHER); return(-4); } } /* Receive the wavesample data, part 1 */ recv_head(NULL); /* Read the head of the incoming message */ mpu_rbyte(); /* Should return 0x0f */ recv12(); /* Should return instrument number */ recv12(); /* Should return layer number */ recv12(); /* Should return wavesample number */ recv_off(); /* Should return beginning of range */ recv_off(); /* Should return end of range */ recv_tail(); /* Read the tail */ /* Send ACK to receive wavesample data Part 2 */ send_response(chan, ACK); /* Ask for next part */ /* Set up some stuff */ max = 0; /* Min. possible sample value (in absolute value) */ /* Receive the wavesample data (Part 2: the actual data) */ recv_head(NULL); for (i = 0, n = from; n < to; n++, i++) { /* Receive and compare the data */ short raw; /* Raw datum */ raw = (short) recv16(); /* Get the next sample */ max = MAX(max,raw); /* Get the max, in absolute value */ max = MAX(max,-raw); /* After 'slice' samples, record and reset the maximum */ if (i == (int) slice) { *out++ = max; max = 0; i = -1; } } recv_tail(); /* Receive end of SysEx */ /* Send ACK to EPS to say that everything has been received * successfully. */ send_response(chan, ACK); wait(BREATHER); return(0); } #ifdef UNDEF /* This version of the routine ought to work, but doesn't, for some * reason. The EPS sends all 512 values, (apparently) receives the * final ACK, then locks up with the "MIDI" indicator blinking. */ /* GET_WSOV * Get an overview of the wavesample described in 'inst'. The result is, * roughly speaking, an array of 512 values, each of which contains the * highest sample value (in absolute value) of that particular 1/512th * of the portion of the wavesample contained between 'from' and 'to'. * The overview is returned in 'out'. * Returns 0 on no error, or a negative error code on error. */ int get_wsov(chan,inst,from,to,out) int chan; /* MIDI channel */ edit_spec *inst; /* Which wavesample? */ ulong from, to; /* Range */ ushort out[512]; /* Description will be put here */ { int i; int waiting; /* Are we waiting for the EPS to do things? */ /* Send request for wavesample overview */ send_head(chan); /* Send SysEx head */ mpu_sbyte(GET_WSOVER); /* Request wavesample overview */ send12(inst->inst_num); /* Instrument number */ send12(inst->layer_num);/* Layer number */ send12(inst->ws_num); /* Wavesample number */ send_off(from); /* Beginning of range */ send_off(to); /* End of range */ send_tail(); /* Send SysEx tail */ if (timeout(SHORT_TIMEOUT)) return(-1); /* Short timeout occurred */ /* This loop is a bit tricky. The basic idea is that the EPS can * send out one of three responses at this point: ACK, WAIT, or * something else. * If it sends an ACK, then all is well, and we can go on to * receive the data. If it sends a something else, then there's * clearly an error, and we can abort with a clean conscience. * If it sends a WAIT, however, then we have to wait for up to * 30 seconds, during which time any of the above can happen, * including a second, third, etc. WAIT message. * If the EPS has sent a WAIT, it will send an ACK before * sending the data (but this was implied by the above para- * graphs). */ waiting = 1; while (waiting) { /* See which response the EPS sends, and react * accordingly. */ switch(recv_response(NULL)) { case ACK: /* Acknowledgement */ waiting = 0; /* Stop waiting */ break; case WAIT: /* Wait for up to 30 seconds */ send_response(chan, ACK); /* Okay, I'll wait */ /* Wait for a timeout */ if (timeout(LONG_TIMEOUT)) return(-3); /* 30-sec timeout * has occurred */ break; default: /* Something's wrong */ wait(BREATHER); return(-4); } } /* Receive the wavesample overview, part 1 */ recv_head(NULL); /* Read the head of the incoming message */ mpu_rbyte(); /* Should return 0x13 */ recv12(); /* Should return instrument number */ recv12(); /* Should return layer number */ recv12(); /* Should return wavesample number */ recv_off(); /* Should return beginning of range */ recv_off(); /* Should return end of range */ recv_tail(); /* Read the tail */ /* Send ACK to receive wavesample overview Part 2 */ send_response(chan, ACK); /* Ask for next part */ /* Receive the wavesample overview (Part 2: the actual data) */ recv_head(NULL); for (i = 0; i < 512; i++) /* Receive the data */ out[i] = recv16(); recv_tail(); /* Receive end of SysEx */ /* Send ACK to EPS to say that everything has been received * successfully. */ wait(BREATHER); return(0); } #endif