home *** CD-ROM | disk | FTP | other *** search
- /* *************** HearHere.c -- The HearHere Toolbox ****************** */
- /* */
- /* Copyright (C) 1990 */
- /* The SID Trio */
- /* All Rights Reserved */
- /* */
- /* */
- /* ********************************************************************* */
-
-
- #include <SoundDvr.h>
- #include "HearHere.h" /* external symbolic definitions */
-
-
-
- /* ********************************************************************* */
- /* */
- /* Internal Symbolic Definitions */
- /* */
- /* ********************************************************************* */
-
- #define MODEM_PORT_CTL 2 /* Offsets to SCC registers */
- #define MODEM_PORT_DATA 6 /* ... */
- #define PRITER_PORT_CTL 0 /* ... */
- #define PRINTER_PORT_DATA 4 /* ... */
-
-
-
- /*****
- * AppleTalk definitions for serial ports
- * Note: these are not used but are given as a reference
- *
- */
- #define SPConfig (*(char *) 0x1fb) /* use types for serial ports */
- #define PortAUse (*(char *) 0x290) /* current use of modem port */
- #define PortBUse (*(char *) 0x291) /* current use of printer port */
- #define useFree 0x80 /* port is unused */
- #define useATalk 1 /* configured for AppleTalk */
- #define useAsync 2 /* configured for the serial driver */
-
-
-
- /*****
- * SCC Definitions
- * Only the registers and bits which are used by HearHere are
- * defined below. For a full description of all of the registers
- * and all of the bit definitions, refer to the Zilog Z8530
- * SCC Serial Communications Controller data sheet.
- *
- */
-
- #define ReadBase (*(char **) 0x1d8) /* SCC base read address */
- #define WriteBase (*(char **) 0x1dc) /* SCC base write address */
-
- /* Read Register 0: transmit/receive buffer
- * status and external status */
- #define RR0 0x00
- #define RXCAVAIL 0x01
-
-
- /* Write Register 0: CRC initialize, initialization
- * commands for the various modes, reg pointers */
- #define WR0 0x00
-
- /* Write Register 1: transmit/receive interrupt
- * and data transfer mode definition */
- #define WR1 0x01
- #define EXTINT 0x01
-
- /* Write Register 3: receive parameters and
- * control */
- #define WR3 0x03
- #define RXENABLE 0x01
- #define RX8BITS 0xc0
-
- /* Write Register 4: transmit/receive miscellaneous
- * parameters and modes */
- #define WR4 0x04
- #define STOP2 0x0c
- #define X1CLOCK 0x00
- #define X16CLOCK 0x40
-
- /* Write Register 5: transmit parameters and
- * control */
- #define WR5 0x05
- #define RTS 0x02
- #define TXENABLE 0x08
- #define SBREAK 0x10
- #define TX8BITS 0x60
-
- /* Write Register 9: master interrupt control
- * and reset */
- #define WR9 0x09
- #define NV 0x02
- #define MIE 0x08
-
- /* Write Register 11: clock mode control */
- #define WR11 0x0b
- #define TCLOCKBR 0x10
- #define RCLOCKTR 0x20
-
- /* Write Register 14: miscellaneous control bits */
- #define WR14 0x0e
- #define BRENABLE 0x01
-
- /* Write Register 15: external/status interrupt
- * control */
- #define WR15 0x0f
- #define DCDINT 0x08
-
-
-
- /*****
- * Miscellaneuos definitions
- *
- */
- #define MAX_ATTEMPTS 1000 /* maximum attempts waiting for valid */
- /* ...audio data before returning FALSE */
- #define MAX_FRONTWINDOW 2500 /* maximum size of a front window */
-
-
-
- /*****
- * Global declarations...
- *
- */
- int HHLastError; /* last error from HearHere */
- int HHRate; /* sampling rate code */
- int HHStartThresh; /* front window starting threshold */
- int HHFrontLength; /* samples in the front window */
- int HHMaxWait; /* max sample wait in front, in 1000's */
- int HHQuietThresh; /* rear window quiet threshold */
- int HHRearLength; /* number of quiet samps in the rear window */
- int HHPort; /* which port is being accessed */
- char *HHCtrlRead; /* SCC read address for ctrl value */
- char *HHCtrlWrite; /* SCC write address for ctrl value */
- char *HHDataRead; /* SCC read address for data value */
- Boolean HHStatus = FALSE; /* TRUE after INIT, FALSE otherwise */
- long SRSave; /* status register after interrupts disabled */
-
-
-
- /*****
- * The data that the various Mac recording devices sends is received
- * in the wrong order from standard serial communications. SoundData
- * is simply a table which will transform the reversed data input into
- * the proper 0-255 level that applications and the Mac toolbox expect.
- *
- */
-
- unsigned char SoundData[] = {
- 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,
- 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
- 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,
- 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
- 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,
- 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
- 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,
- 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
- 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,
- 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
- 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,
- 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
- 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,
- 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
- 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,
- 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
- 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,
- 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
- 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,
- 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
- 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,
- 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
- 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,
- 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
- 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,
- 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
- 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,
- 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
- 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,
- 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
- 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,
- 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
- };
-
-
-
-
- /* ********************************************************************* */
- /* */
- /* *** The Toolbox *** */
- /* */
- /* ********************************************************************* */
-
-
-
- /*****
- * HHInit -- Initializes the SCC for the audio device
- * Parameter: port - MODEM_PORT or PRINTER_PORT
- * Returns: TRUE - valid port
- * FALSE - invalid port or port assigned to AppleTalk or
- * the port is in use - check HHError() for reason
- * Notes: This routine turns on the green light of the
- * Impulse sound digitizer
- *
- */
- Boolean HHInit(port)
- int port;
- {
- register unsigned char *ctrl,*data;
- register int attempts;
- int i;
- long currentTicks;
- char c;
-
- HHStatus = FALSE;
-
- if (port == MODEM_PORT) {
- HHCtrlRead = ReadBase + 2;
- HHCtrlWrite = WriteBase + 2;
- HHDataRead = ReadBase + 6;
- }
- else
- if (port == PRINTER_PORT) {
- HHCtrlRead = ReadBase + 0;
- HHCtrlWrite = WriteBase + 0;
- HHDataRead = ReadBase + 4;
- }
- else {
- HHLastError = INVALID_PORT;
- return FALSE;
- }
-
- HHPort = port; /* save the port being accessed */
-
- /*****
- * Set up the SCC for the audio device
- *
- */
- SCCSet(WR9,NV);
- SCCSet(WR1,EXTINT); /* external interrupt is for mouse... */
- SCCSet(WR3,(RXENABLE | RX8BITS));
- SCCSet(WR4,(STOP2 | X1CLOCK));
- SCCSet(WR5,(RTS | TXENABLE | SBREAK | TX8BITS));
- SCCSet(WR11,(TCLOCKBR | RCLOCKTR));
- SCCSet(WR14,BRENABLE);
- SCCSet(WR15,DCDINT); /* CD interrupt for mouse... */
- SCCSet(WR9,(NV | MIE)); /* initialize master interrupt and NV */
-
- /*****
- * Check to make sure that the audio device is
- * really out there...
- *
- */
- Delay(1L,¤tTicks); /* delay for 1/60 second */
- ctrl = (unsigned char *) HHCtrlRead;
- data = (unsigned char *) HHDataRead;
- for (i = 0; i < 5; i++) {
- attempts = 0;
- while ((*ctrl & 0x01) == 0)
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING;
- return FALSE;
- }
- attempts = attempts;
- c = *data;
- }
-
- /*****
- * Set default internal conditions
- *
- */
- HHLastError = 0;
- HHRate = 1; /* default to 22K samples/sec */
- HHStartThresh = 0; /* no threshold needed */
- HHFrontLength = 0; /* no front window length */
- HHMaxWait = 0; /* no timeout possible... */
- HHQuietThresh = 0; /* samples are never quiet */
- HHRearLength = 0; /* no rear window length */
-
- HHStatus = TRUE;
- return TRUE;
- }
-
-
-
- /*****
- * SCCSet -- Sets an SCC register with a value
- * Parameters: reg - the SCC register
- * value - the value to set
- *
- */
- SCCSet(reg,value)
- char reg,value;
- {
- *HHCtrlWrite = reg; /* set SCC register */
- *HHCtrlWrite = value; /* put the value into the reg */
-
- reg = reg; /* add some delay... */
- reg = reg;
- }
-
-
-
- /*****
- * HHSample -- Return the current level of the audio device
- * Parameter: level - returned value
- * Returns: TRUE - value returned
- * FALSE - check HHError() for error code
- *
- */
- Boolean HHSample(level)
- int *level;
- {
- register unsigned char *data,*ctrl;
- register int attempts;
-
- if (!HHStatus) {
- HHLastError = UNKNOWN_STATE;
- return FALSE;
- }
-
- ctrl = (unsigned char *) HHCtrlRead;
- data = (unsigned char *) HHDataRead;
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0)
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING;
- return FALSE;
- }
-
- *level = SoundData[*data] & 0xff;
- return TRUE;
- }
-
-
-
- /*****
- * HHSampleRate -- Sets the sampling rate used in HHRecord
- * Parameter: rate - sampling rate coefficient where:
- * Sample rate = 22000 / rate
- *
- * rate sampling
- * 1 22254 samples/sec
- * 2 11127 samples/sec
- * 3 7418 samples/sec
- * 4 5564 samples/sec
- *
- * Returns: TRUE - rate set
- * FALSE - check HHError() for error code
- * Note: Each sample uses one byte of memory...
- *
- */
- Boolean HHSampleRate(rate)
- int rate;
- {
- if (!HHStatus) {
- HHLastError = UNKNOWN_STATE;
- return FALSE;
- }
-
- if (rate <= 0 || rate > 4) {
- HHLastError = INVALID_RATE;
- return FALSE;
- }
-
- HHRate = rate;
- return TRUE;
- }
-
-
-
- /*****
- * HHFrontWindow -- Sets the recording front window parameters
- * Parameters: startThresh - threshold of a valid sound
- * frontLength - num of samples to save before sound starts
- * maxWait - maximum number of samples to wait (in 1000's)
- * Returns: TRUE - front window set
- * FALSE - check HHError() for error code
- * Note: Setting maxWait to -1 will force an indefinite wait
- * in a record until a sound is made satisfying the
- * threshold conditions.
- *
- */
- Boolean HHFrontWindow(startThresh,frontLength,maxWait)
- int startThresh,frontLength,maxWait;
- {
- if (!HHStatus) {
- HHLastError = UNKNOWN_STATE;
- return FALSE;
- }
-
- if ((startThresh < 0) || (frontLength < 0) || (maxWait < -1)) {
- HHLastError = INVALID_FRONT;
- return FALSE;
- }
-
- if (frontLength > MAX_FRONTWINDOW) {
- HHLastError = INVALID_FRONT;
- return FALSE;
- }
-
- HHStartThresh = startThresh;
- HHFrontLength = frontLength;
- HHMaxWait = maxWait;
- return TRUE;
- }
-
-
-
- /*****
- * HHRearWindow -- Sets the recording rear window parameters
- * Parameters: quietThresh - threshold of "quiet"
- * rearLength - num of quiet samps needed to end recording
- * Returns: TRUE - rear window set
- * FALSE - check HHError() for error code
- * Note: Setting rearLength to zero causes a recording to
- * never end because of quietness.
- *
- */
- Boolean HHRearWindow(quietThresh,rearLength)
- int quietThresh,rearLength;
- {
- if (!HHStatus) {
- HHLastError = UNKNOWN_STATE;
- return FALSE;
- }
-
- if ((quietThresh < 0) || (rearLength < 0)) {
- HHLastError = INVALID_REAR;
- return FALSE;
- }
-
- HHQuietThresh = quietThresh;
- HHRearLength = rearLength;
- return TRUE;
- }
-
-
- /*****
- * HHRecord -- Record data from the audio device based on HH settings
- * Parameters: buffer - address of where to put the data
- * bufLen - the maximum number of samples to record
- * diskUse - 0 for RAM recording, otherwise it is the refNum
- * of a previously opened hard disk file
- * mouseFlag - TRUE: mouse movement *WILL* stop recording
- * FALSE: movement will not stop recording
- * recordLen - the actual number of samples recorded
- * positive value: recording ended via rear window
- * negative value: recording ended because of mouse
- * -1: recording filled buffer completely
- * Returns: TRUE - recording done, check recordLen for more info
- * FALSE - check HHError() for error code
- * Note: Based on the sample rate, this routine just calls
- * one of the two recording routines. This is needed
- * because at the highest sampling rate, excess code
- * needs to be removed to guarantee high quality
- * recording on all Macintoshes.
- *
- */
- Boolean HHRecord(buffer,bufLen,diskUse,mouseFlag,recordLen)
- unsigned char *buffer;
- long bufLen;
- int diskUse;
- Boolean mouseFlag;
- long *recordLen;
- {
- if (HHRate == 1)
- return HHRecHigh(buffer,bufLen,diskUse,mouseFlag,recordLen);
- else
- return HHRecLow(buffer,bufLen,diskUse,mouseFlag,recordLen);
- }
-
-
-
- /*****
- * HHRecHigh -- Record data from the audio device at high rate
- * Note: This routine is an internal process routine for HHRecord.
- * It handles recording when the data rate is at the 22K rate
- * because it leaves out some data checks to make the processing
- * faster, especially when it is run on a MacPlus or SE.
- *
- * If disk recording is requested, this routine just calls another
- * routine which handles high data rate recording to disk.
- *
- */
- Boolean HHRecHigh(buffer,bufLen,diskUse,mouseFlag,recordLen)
- unsigned char *buffer;
- long bufLen;
- int diskUse;
- Boolean mouseFlag;
- long *recordLen;
- {
- register unsigned char *data,*ctrl;
- register unsigned char *bufInsert;
- register unsigned char upperLimit,lowerLimit,level;
- register int attempts,vInt;
- register long vLong;
- unsigned char quietUpper,quietLower;
- unsigned char frontWindow[MAX_FRONTWINDOW];
- unsigned char *bufEnd;
- int *intPtr,prevFlag,constant;
- Boolean filled; /* TRUE when frontWindow gets filled */
- Boolean interrupt; /* TRUE when interrupt occured */
- int i;
-
-
- if (!HHStatus) {
- HHLastError = UNKNOWN_STATE;
- return FALSE;
- }
-
- /*****
- * Handle recording to disk in a completely separate way.
- * This allows some developers the option of leaving out
- * this module completely if it is not appropriate for
- * their application.
- *
- */
- if (diskUse != 0)
- return HHRecToDiskHigh(buffer,bufLen,diskUse,mouseFlag,recordLen);
-
- /*****
- * Set up as required variables
- *
- */
- ctrl = (unsigned char *) HHCtrlRead;
- data = (unsigned char *) HHDataRead;
- bufInsert = frontWindow;
- upperLimit = 128 + HHStartThresh;
- lowerLimit = 128 - HHStartThresh;
- quietUpper = 128 + HHQuietThresh;
- quietLower = 128 - HHQuietThresh;
- vLong = HHMaxWait * 1000L;
- filled = FALSE;
- interrupt = FALSE;
-
- if (mouseFlag)
- intPtr = (int *) 0x828; /* interrupt flag */
- else
- intPtr = &constant; /* never changes... */
- prevFlag = *intPtr;
-
-
- /*****
- * Wait for the front window
- *
- */
- while (vLong-- > 0) {
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (*intPtr != prevFlag) { /* interrupt? */
- *recordLen = 0;
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
-
- *bufInsert++ = level; /* save it away */
-
- if (bufInsert == &frontWindow[MAX_FRONTWINDOW]) {
- bufInsert = frontWindow;
- filled = TRUE; /* circle around the buffer... */
- }
-
- if (level < lowerLimit || level > upperLimit)
- break;
- }
-
- if (vLong <= 0L) {
- HHLastError = TIMEOUT;
- return FALSE;
- }
-
-
- /*****
- * Front window is satisfied. Now read the remaining
- * sound data until the front window or mouse condition
- * is met...
- *
- */
-
- vLong = (long) bufInsert; /* save last location of front window */
- bufInsert = buffer + HHFrontLength; /* leave room for front window */
- upperLimit = quietUpper; /* get new limits... */
- lowerLimit = quietLower; /* ... */
- vInt = 0; /* count of number of "quiet" samples */
- bufEnd = buffer + bufLen; /* last buffer location */
-
- if (HHRearLength != 0) {
-
- /*****
- * There IS a rear window
- *
- */
- while (vInt < HHRearLength) {
-
- if (*intPtr != prevFlag) { /* interrupt? */
- interrupt = TRUE;
- goto EscapeLoop;
- }
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
-
- if (level > lowerLimit && level < upperLimit)
- vInt++;
- else
- vInt = 0;
-
- *bufInsert++ = level; /* save it away */
-
- if (bufInsert == bufEnd) /* at end of buffer? */
- break; /* yes, stop here */
- }
-
- }
-
- else {
- /*****
- * There is not a rear window
- *
- */
- while (bufInsert != bufEnd) {
-
- if (*intPtr != prevFlag) { /* interrupt? */
- interrupt = TRUE;
- goto EscapeLoop;
- }
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
-
- *bufInsert++ = level; /* save it away */
-
- }
-
- }
-
- EscapeLoop:
- if (bufInsert == bufEnd)
- *recordLen = -1;
- else
- *recordLen = (long) bufInsert - (long) buffer;
-
-
- /*****
- * Put the front window into the data buffer
- *
- */
- bufInsert = (unsigned char *) vLong; /* last byte of front */
- data = buffer + HHFrontLength; /* last loc in buffer */
-
- while (data > buffer) {
- if (bufInsert == frontWindow)
- if (filled)
- bufInsert = &frontWindow[MAX_FRONTWINDOW];
- else {
- *--data = 128; /* fill with quiet */
- continue;
- }
-
- *--data = *--bufInsert; /* put in next from front */
- }
-
- if (interrupt) {
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- return TRUE;
- }
-
-
-
- /*****
- * HHRecLow -- Record data from the audio device at lower sampling rates
- * Note: This routine is an internal process routine for HHRecord.
- * It handles recording when the data rate is less than the
- * 22K rate.
- *
- * If disk recording is requested, this routine just calls another
- * routine which handles low data rate recording to disk.
- *
- */
- Boolean HHRecLow(buffer,bufLen,diskUse,mouseFlag,recordLen)
- unsigned char *buffer;
- long bufLen;
- int diskUse;
- Boolean mouseFlag;
- long *recordLen;
- {
- register unsigned char *data,*ctrl;
- register unsigned char *bufInsert;
- register unsigned char upperLimit,lowerLimit,level;
- register int attempts,vInt;
- long vLong;
- unsigned char quietUpper,quietLower;
- unsigned char frontWindow[MAX_FRONTWINDOW];
- unsigned char *bufEnd;
- int *intPtr,prevFlag,constant;
- Boolean filled; /* TRUE when frontWindow gets filled */
- Boolean interrupt; /* TRUE when interrupt occured */
- int i;
-
-
- if (!HHStatus) {
- HHLastError = UNKNOWN_STATE;
- return FALSE;
- }
-
- /*****
- * Handle recording to disk in a completely separate way.
- * This allows some developers the option of leaving out
- * this module completely if it is not appropriate for
- * their application.
- *
- */
- if (diskUse != 0)
- return HHRecToDiskLow(buffer,bufLen,diskUse,mouseFlag,recordLen);
-
- /*****
- * Set up as required variables
- *
- */
- ctrl = (unsigned char *) HHCtrlRead;
- data = (unsigned char *) HHDataRead;
- bufInsert = frontWindow;
- upperLimit = 128 + HHStartThresh;
- lowerLimit = 128 - HHStartThresh;
- quietUpper = 128 + HHQuietThresh;
- quietLower = 128 - HHQuietThresh;
- vLong = HHMaxWait * 1000L;
- filled = FALSE;
- interrupt = FALSE;
-
- if (mouseFlag)
- intPtr = (int *) 0x828; /* interrupt flag */
- else
- intPtr = &constant; /* never changes... */
- prevFlag = *intPtr;
-
-
- /*****
- * Wait for the front window
- *
- */
- while (vLong-- > 0) {
-
- for (vInt = 0; vInt < HHRate; vInt++) { /* handle samp rate */
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (*intPtr != prevFlag) { /* interrupt? */
- *recordLen = 0;
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
- }
-
- *bufInsert++ = level; /* save it away */
-
- if (bufInsert == &frontWindow[MAX_FRONTWINDOW]) {
- bufInsert = frontWindow;
- filled = TRUE; /* circle around the buffer... */
- }
-
- if (level < lowerLimit || level > upperLimit)
- break;
- }
-
- if (vLong <= 0L) {
- HHLastError = TIMEOUT;
- return FALSE;
- }
-
- /*****
- * Front window is satisfied. Now read the remaining
- * sound data until the front window or mouse condition
- * is met...
- *
- */
-
- vLong = (long) bufInsert; /* save last location of front window */
- bufInsert = buffer + HHFrontLength; /* leave room for front window */
- upperLimit = quietUpper; /* get new limits... */
- lowerLimit = quietLower; /* ... */
- vInt = 0; /* count of number of "quiet" samples */
- bufEnd = buffer + bufLen; /* last buffer location */
-
- if (HHRearLength != 0) {
-
- /*****
- * There IS a rear window
- *
- */
- while (vInt < HHRearLength) {
-
- if (*intPtr != prevFlag) { /* interrupt? */
- interrupt = TRUE;
- goto EscapeLoop;
- }
-
- for (i = 0; i < HHRate; i++) {
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
- }
-
- if (level > lowerLimit && level < upperLimit)
- vInt++;
- else
- vInt = 0;
-
- *bufInsert++ = level; /* save it away */
-
- if (bufInsert == bufEnd) /* at end of buffer? */
- break; /* yes, stop here */
- }
-
- }
-
- else {
- /*****
- * There is not a rear window
- *
- */
- while (bufInsert != bufEnd) {
-
- if (*intPtr != prevFlag) { /* interrupt? */
- interrupt = TRUE;
- goto EscapeLoop;
- }
-
- for (i = 0; i < HHRate; i++) {
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
- }
-
- *bufInsert++ = level; /* save it away */
-
- }
-
- }
-
- EscapeLoop:
- if (bufInsert == bufEnd)
- *recordLen = -1;
- else
- *recordLen = (long) bufInsert - (long) buffer;
-
-
- /*****
- * Put the front window into the data buffer
- *
- */
- bufInsert = (unsigned char *) vLong; /* last byte of front */
- data = buffer + HHFrontLength; /* last loc in buffer */
-
- while (data > buffer) {
- if (bufInsert == frontWindow)
- if (filled)
- bufInsert = &frontWindow[MAX_FRONTWINDOW];
- else {
- *--data = 128; /* fill with quiet */
- continue;
- }
-
- *--data = *--bufInsert; /* put in next from front */
- }
-
- if (interrupt) {
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- return TRUE;
- }
-
-
-
- /*****
- * HHRecToDiskHigh -- Record data from the audio device directly to disk
- * at 22 KHz sampling rate. This routine is needed
- * because at this rate, code must be taken out in order
- * to record properly on 8 MHz Macs (SE's and Plus's).
- * Note: This routine is an internal process routine for HHRecord.
- * It handles the recording of sound input directly to disk
- * by double-buffering the data to writing to disk with
- * asynchronous I/O's
- *
- */
- Boolean HHRecToDiskHigh(buffer,bufLen,diskUse,mouseFlag,recordLen)
- unsigned char *buffer;
- long bufLen;
- int diskUse;
- Boolean mouseFlag;
- long *recordLen;
- {
- register unsigned char *data,*ctrl;
- register unsigned char *bufInsert;
- register unsigned char upperLimit,lowerLimit,level;
- register int attempts,vInt;
- long vLong;
- unsigned char quietUpper,quietLower;
- unsigned char frontWindow[MAX_FRONTWINDOW];
- unsigned char *bufEnd;
- unsigned char *altBuffer;
- int whichBuffer;
- int *intPtr,prevFlag,constant;
- Boolean filled; /* TRUE when frontWindow gets filled */
- Boolean interrupt; /* TRUE when interrupt occured */
- int i;
- IOParam iop;
- OSErr err;
-
- altBuffer = (unsigned char *) buffer + (bufLen >> 1);
- bufLen >>= 1;
-
- whichBuffer = 1;
- *recordLen = 0;
- bufLen--;
-
- iop.ioCompletion = 0L;
- iop.ioRefNum = diskUse;
- iop.ioVersNum = 0;
- iop.ioPermssn = fsWrPerm;
- iop.ioMisc = 0L;
- iop.ioPosMode = 0;
- iop.ioPosOffset = 0L;
- iop.ioResult = 0;
-
- /*****
- * Set up as required variables
- *
- */
- ctrl = (unsigned char *) HHCtrlRead;
- data = (unsigned char *) HHDataRead;
- bufInsert = frontWindow;
- upperLimit = 128 + HHStartThresh;
- lowerLimit = 128 - HHStartThresh;
- quietUpper = 128 + HHQuietThresh;
- quietLower = 128 - HHQuietThresh;
- vLong = HHMaxWait * 1000L;
- filled = FALSE;
- interrupt = FALSE;
-
- if (mouseFlag)
- intPtr = (int *) 0x828; /* interrupt flag */
- else
- intPtr = &constant; /* never changes... */
- prevFlag = *intPtr;
-
- while (1) {
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (*intPtr != prevFlag) { /* interrupt? */
- *recordLen = 0;
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
-
- if (level < lowerLimit || level > upperLimit)
- break;
- }
-
-
-
- bufInsert = (unsigned char *) buffer;
- upperLimit = quietUpper; /* get new limits... */
- if (HHRearLength == 0)
- upperLimit = 0; /* no rear window */
- lowerLimit = quietLower; /* ... */
- vInt = 0; /* count of number of "quiet" samples */
- bufEnd = (unsigned char *) (buffer + bufLen); /* last buffer location */
-
-
- while (vInt <= HHRearLength) {
-
- if (*intPtr != prevFlag) { /* interrupt? */
- interrupt = TRUE;
- goto EscapeLoop;
- }
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
-
- if (level > lowerLimit && level < upperLimit)
- vInt++;
- else
- vInt = 0;
-
- *bufInsert++ = level; /* save it away */
-
- if (bufInsert == bufEnd) {
- if (whichBuffer == 1) {
- iop.ioBuffer = (Ptr) buffer;
- bufInsert = (unsigned char *) altBuffer;
- bufEnd = (unsigned char *) (altBuffer + bufLen);
- whichBuffer = 2;
- }
- else {
- iop.ioBuffer = (Ptr) altBuffer;
- bufInsert = (unsigned char *) buffer;
- bufEnd = (unsigned char *) (buffer + bufLen);
- whichBuffer = 1;
- }
- iop.ioReqCount = bufLen;
- err = PBWrite(&iop,TRUE);
- if (err != noErr) {
- HHLastError = DISKFAIL;
- return FALSE;
- }
- (*recordLen) += bufLen;
- }
-
- }
-
- EscapeLoop:
-
- while (iop.ioResult > 0)
- ;
-
- while (bufInsert < bufEnd)
- *bufInsert++ = 128; /* fill out buffer with silence */
-
- if (whichBuffer == 1) {
- iop.ioBuffer = (Ptr) buffer;
- }
- else {
- iop.ioBuffer = (Ptr) altBuffer;
- }
- iop.ioReqCount = bufLen;
- err = PBWrite(&iop,FALSE);
- if (err != noErr) {
- HHLastError = DISKFAIL;
- return FALSE;
- }
-
- (*recordLen) += bufLen;
-
-
- if (interrupt) {
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- return TRUE;
- }
-
-
-
- /*****
- * HHRecToDiskLow -- Record data from the audio device directly to disk
- * at lower than 22 KHz sampling rate.
- * Note: This routine is an internal process routine for HHRecord.
- * It handles the recording of sound input directly to disk
- * by double-buffering the data to writing to disk with
- * asynchronous I/O's
- *
- */
- Boolean HHRecToDiskLow(buffer,bufLen,diskUse,mouseFlag,recordLen)
- unsigned char *buffer;
- long bufLen;
- int diskUse;
- Boolean mouseFlag;
- long *recordLen;
- {
- register unsigned char *data,*ctrl;
- register unsigned char *bufInsert;
- register unsigned char upperLimit,lowerLimit,level;
- register int attempts,vInt;
- long vLong;
- unsigned char quietUpper,quietLower;
- unsigned char frontWindow[MAX_FRONTWINDOW];
- unsigned char *bufEnd;
- unsigned char *altBuffer;
- int whichBuffer;
- int *intPtr,prevFlag,constant;
- Boolean filled; /* TRUE when frontWindow gets filled */
- Boolean interrupt; /* TRUE when interrupt occured */
- int i;
- IOParam iop;
- OSErr err;
-
- altBuffer = (unsigned char *) buffer + (bufLen >> 1);
- bufLen >>= 1;
-
- whichBuffer = 1;
- *recordLen = 0;
- bufLen--;
-
- iop.ioCompletion = 0L;
- iop.ioRefNum = diskUse;
- iop.ioVersNum = 0;
- iop.ioPermssn = fsWrPerm;
- iop.ioMisc = 0L;
- iop.ioPosMode = 0;
- iop.ioPosOffset = 0L;
- iop.ioResult = 0;
-
- /*****
- * Set up as required variables
- *
- */
- ctrl = (unsigned char *) HHCtrlRead;
- data = (unsigned char *) HHDataRead;
- bufInsert = frontWindow;
- upperLimit = 128 + HHStartThresh;
- lowerLimit = 128 - HHStartThresh;
- quietUpper = 128 + HHQuietThresh;
- quietLower = 128 - HHQuietThresh;
- vLong = HHMaxWait * 1000L;
- filled = FALSE;
- interrupt = FALSE;
-
- if (mouseFlag)
- intPtr = (int *) 0x828; /* interrupt flag */
- else
- intPtr = &constant; /* never changes... */
- prevFlag = *intPtr;
-
- while (1) {
-
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (*intPtr != prevFlag) { /* interrupt? */
- *recordLen = 0;
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
-
- if (level < lowerLimit || level > upperLimit)
- break;
- }
-
- bufInsert = (unsigned char *) buffer;
- upperLimit = quietUpper; /* get new limits... */
- if (HHRearLength == 0)
- upperLimit = 0; /* no rear window */
- lowerLimit = quietLower; /* ... */
- vInt = 0; /* count of number of "quiet" samples */
- bufEnd = (unsigned char *) (buffer + bufLen); /* last buffer location */
-
-
- while (vInt <= HHRearLength) {
-
- if (*intPtr != prevFlag) { /* interrupt? */
- interrupt = TRUE;
- goto EscapeLoop;
- }
-
- for (i = 0; i < HHRate; i++) {
- attempts = 0;
-
- while ((*ctrl & 0x01) == 0) { /* still alive? */
- if (++attempts > MAX_ATTEMPTS) {
- HHLastError = NOT_RESPONDING; /* no, error... */
- return FALSE;
- }
- }
-
- level = SoundData[*data]; /* get current level */
- }
-
- if (level > lowerLimit && level < upperLimit)
- vInt++;
- else
- vInt = 0;
-
- *bufInsert++ = level; /* save it away */
-
- if (bufInsert == bufEnd) {
- if (whichBuffer == 1) {
- iop.ioBuffer = (Ptr) buffer;
- bufInsert = (unsigned char *) altBuffer;
- bufEnd = (unsigned char *) (altBuffer + bufLen);
- whichBuffer = 2;
- }
- else {
- iop.ioBuffer = (Ptr) altBuffer;
- bufInsert = (unsigned char *) buffer;
- bufEnd = (unsigned char *) (buffer + bufLen);
- whichBuffer = 1;
- }
- iop.ioReqCount = bufLen;
- err = PBWrite(&iop,TRUE);
- if (err != noErr) {
- HHLastError = DISKFAIL;
- return FALSE;
- }
- (*recordLen) += bufLen;
- }
-
- }
-
- EscapeLoop:
-
- while (iop.ioResult > 0)
- ;
-
- while (bufInsert < bufEnd)
- *bufInsert++ = 128; /* fill out buffer with silence */
-
- if (whichBuffer == 1) {
- iop.ioBuffer = (Ptr) buffer;
- }
- else {
- iop.ioBuffer = (Ptr) altBuffer;
- }
- iop.ioReqCount = bufLen;
- err = PBWrite(&iop,FALSE);
- if (err != noErr) {
- HHLastError = DISKFAIL;
- return FALSE;
- }
-
- (*recordLen) += bufLen;
-
-
- if (interrupt) {
- HHLastError = INTERRUPT;
- return FALSE;
- }
-
- return TRUE;
- }
-
-
-
- /*****
- * HHDiskPlay -- Outputs previously recorded sound from a disk file
- * Parameters: refNum - the refNum of an open file
- * buffer - a buffer to use for inputting data from the disk
- * bufLen - the length of the buffer
- * Returns: TRUE - successful play
- * FALSE - check HHError() for error code
- *
- */
- Boolean HHDiskPlay(refNum,buffer,bufLen)
- int refNum;
- unsigned char *buffer;
- long bufLen;
- {
- int whichBuffer;
- long len,ioCount;
- long ticks;
- FFSynthPtr b1,b2,b;
- OSErr err;
-
- StopSound();
- b1 = (FFSynthPtr) buffer;
- b2 = (FFSynthPtr) ((char *) buffer + (bufLen >> 1));
- b1->mode = ffMode;
- b1->count = FixRatio(1,HHRate);
- b2->mode = ffMode;
- b2->count = FixRatio(1,HHRate);
- whichBuffer = 1;
- len = (bufLen >> 1) - 10;
-
- SetSoundVol(7);
-
- ioCount = len;
- err = FSRead(refNum,&ioCount,b1->waveBytes);
- if (ioCount == 0L) {
- HHLastError = DISKFAIL;
- return FALSE;
- }
-
- StartSound(b1,ioCount,0L);
- Delay(60,&ticks); /* don't know why I need this...but I do... */
-
- while (err == noErr) {
- whichBuffer = 3 - whichBuffer;
- if (whichBuffer == 1) {
- b = b1;
- }
- else {
- b = b2;
- }
-
- ioCount = len;
- err = FSRead(refNum,&ioCount,b->waveBytes);
-
- if (err == noErr) {
- while (SoundDone() == FALSE)
- ;
- StartSound(b,ioCount,0L);
- }
- }
-
- while (SoundDone() == FALSE)
- ;
-
- return TRUE;
- }
-
-
-
-
- /*****
- * HHDisableInts -- Disables all interrupts on the Macintosh
- * (Included as part of the toolbox to show how to disable interrupts)
- *
- */
- void HHDisableInts()
- {
- asm {
- move sr,SRSave
- ori #0x700,sr
- }
- }
-
-
-
- /*****
- * HHEnableInts -- Re-enables all interrupts on the Macintosh
- * (Included as part of the toolbox to show how to enable interrupts)
- *
- */
- void HHEnableInts()
- {
- asm {
- move SRSave,sr /* enable interrupts */
- }
- }
-
-
-
- /*****
- * HHEnd -- Closes communications with the audio device
- * Note: If HHLastError is set to -1 then HHEnd will be
- * allowed to be processed when HHInit wasn't called.
- * This allows the resetting of the use flags for
- * a developer who knows what they are doing...
- *
- */
- Boolean HHEnd()
- {
- if (!HHStatus && (HHLastError != -1)) {
- HHLastError = UNKNOWN_STATE;
- return FALSE;
- }
-
- SCCSet(WR5,0); /* turn off recording reference */
-
- HHStatus = FALSE; /* no longer init'd */
- }
-
-
-
- /*****
- * HHError -- Return the last error generated in HearHere
- *
- */
- int HHError()
- {
- return HHLastError;
- }
-
-
-
-
-
- /* ********************************************************************* */
- /* */
- /* End of HearHere.c */
- /* */
- /* ********************************************************************* */
-