This is DEController.h in view mode; [Download] [Up]
/* * DEController Object * Copyright 1989 Metaresearch, Inc. * * Created 10/10/89 by A. D. Laird * * Modifications: * * Description: * * The DEController object is a subclass of the NeXT Sound object that offers * increased functionality and performance for users who desire more control over * the DSP port and the sound data that enters the NeXT. In addition, the * DEController does all of the necessary memory stream allocation so that data of * arbitrary length can reliably be recorded from the DSP. For information on the * Sound object, users should consult the documentation for the Sound object in * the NeXT Reference Manual. * * The recording mechanism used by the DEController is based upon the DERecorder * object, a preliminary version of a general memory/stream control object that * will soon be available from Metaresearch. This method differs significantly * from that used by the Sound object. Consequently, users of the DEController * should NOT use the following methods that are implemented by the Sound object : * * - soundStructBeingProcessed - soundBeingProcessed * * Before data may be recorded, the appropriate memory channels must be set up, * and for recording from the DSP port, an assembler program must be downloaded to * the DSP. This initialization is done via the prepareToRecord: method and takes * about a second. If you do not call this method prior to recording, it is * called automatically before the recording actually begins. Thus, if it is * important to start recording exactly, call prepareToRecord: first. The * recording is prepared according to the parameters specified when the * DEController is created, or when you call the * setDataSize:dataFormat:samplingRate:channelCount:infoSize: method. * * When the recording is prepared, incoming data begins streaming to the delegate * via the dataBeingRecorded::: method (if implemented), but it is not written to * disk. The data begins writing to disk as soon as the record method is called. * Recording may be paused by calling the pause method. Data continues to be sent * to the delegate, though it stops writing to disk. To resume recording, call * resume. * * Playback of a sound is accomplished by sending the play message to the * DEController. To begin playback from somewhere other than the beginning of the * sound, use playFrom: instead. For very large sounds, offsetting the sound data * may take a fraction of a second; thus, if it is important to begin playback at * an exact moment, call the prepareToPlayFrom: method first. A sound which is * playing may also be paused and resumed, though when it is paused, data is not * sent to the delegate. * * In addition to the delegate methods provided by the Sound object, the * DEController's delegate may also implement the following methods : * * - playPaused: Called after playback is paused * - playResumed: Called after playback resumes from a pause * - recordReady: Called after the NeXT is set up for recording * - recordPaused: Called after recording is paused * - recordResumed: Called after recording resumes from a pause * - dataBeingPlayed::: Called during playback of sound * - dataBeingRecorded::: Called during recording, even if paused * * The last two methods should be implemented by the DEController's delegate if * the data is to be processed further (to draw scope traces, animate meters, * compute voltage values, etc.). When processing the data it is important to * know how many bytes per frame (channel-independent) are contained in the data. * This can be obtained by querying the DEController with the bytesPerFrame * message. * * During recording, the DEController's delegate is sent the dataBeingRecorded::: * message for every block of data that enters the DSP or CODEC. If the delegate * does extensive processing or graphing of the data, the block may not be written * to disk in time for the next block to be accurately recorded. For example, for * stereo DSP recording at 44.1 kHz sampling, the dataBeingRecorded::: method is * called over 40 times every second with around 1024 data points each time. For * simple animation and computations this poses no problem; however, if your * delegate does extensive computation and graphics (e.g. if it computes the * Fourier transform on the data, draws the original trace, and then draws the * Fourier trace) there is no possible way to perform all of those operations 40 * times a second. Depending upon the amount of additional processing your * delegate does, you may wish to process only every other chunk of data, or every * third, fourth or fifth chunk of data. Though this may seem like a lot of * effort, it is the fastest way that you can manage the data in real time. If * you do not care if a little bit of information is lost, you may do whatever you * like to the data; the next chunk will be sent after all of your processing is * done. If it is critical that no data be lost, and you wish to do extensive * computations and animation with the data, the best alternative is to record the * data and save it to disk first with no additional processing, then process each * chunk of (saved) data separately as fast as your particular processing scheme * allows. This will likely not be in realtime, but no data will be lost. * * If you only want to look at the incoming data , use the startTrace: method to * begin streaming in data from the specified input. The data is sent to the * delegate via the dataBeingRecorded::: method (the same as for recording), * except that it is not written to disk. To stop this data transfer, call the * stopTrace: method. This "trace mode" will be disabled before recording or * playing any data. * * Please refer to the DEController documentation for more details about using * the dataBeingPlayed::: and dataBeingRecorded::: delegate methods. */ #import <soundkit/Sound.h> #define APP_FOLDER "AppFolder" #define DSP_RECORD "/usr/lib/sound/dsprecord.snd" float SNDSamplesToSeconds(int sampleCount, int channelCount, float samplingRate); int SNDSecondsToSamples(float secondCount, int channelCount, float samplingRate); @interface DEController : Sound { BOOL traceOn; // YES if trace mode is active char recordPath[1024]; // location to save new recording int offsetSamps; // num samps to offset data for playFrom: int offsetBytes; // num bytes to offset data for playFrom: int recordedBytes; // num bytes recorded to disk int curErr; // current error num generated by object id derecorder; // recorder object; controls DMA streams id timer; // animator object; sends data during playback id openPan; // pointer to Open Panel id savePan; // pointer to Save Panel /* Private Variables */ BOOL _doSend; int _recFD, _maxSamps, _bytespersample; char *_curData; } + new; + newFromSoundfile:(char *)filename; /****************************************************************************** * * The following methods are defined in the Sound object and are * reimplemented in order for the DEController to function * properly. Comments are added where the method functions differently * from that described in the Sound object. * ******************************************************************************/ - (int)pause; - pause:sender; /* * Pauses any recording or playback of the sound. If the object is * currently recording, data continues to be sent to the delegate via * the dataBeingRecorded::: method, though it is not written to disk. * If the object is currently playing, the object's delegate is no * longer sent the dataBeingPlayed::: message. After the playback * or recording pauses, the object's delegate is sent the playPaused: * or recordPaused: message, respectively. */ - (int)play; - play:sender; /* * Begins playback of sound data through the NeXT. During playback, * the object's delegate is constantly sent the data that is currently * being played via the dataBeingPlayed::: method (if implemented). */ - (int)record; - record:sender; /* * Begins actual recording of data. If the prepareToRecord: method * (described below) has not been called before this method, it is done * just before the recording begins. The parameters for recording are set * when the DEController is read from disk, or when the Sound object method, * setDataSize:dataFormat:samplingRate:channelCount:infoSize: is called. */ - (int)resume; - resume:sender; /* * Resumes recording or playback of the sound. After the playback * or recording resumes, the object's delegate is sent the playResumed: * or recordResumed: message, respectively. */ - (int)stop; - stop:sender; - (int)waitUntilStopped; - (int)sampleCount; - (int)samplesProcessed; - (int)status; /* * Returns the current status of the DEController, which may be * one of the following: * * SK_STATUS_INITIALIZED SK_STATUS_STOPPED * SK_STATUS_PLAYING_PENDING SK_STATUS_RECORDING_PENDING * SK_STATUS_PLAYING SK_STATUS_RECORDING * SK_STATUS_PLAYING_PAUSED SK_STATUS_RECORDING_PAUSED */ - (int)processingError; /****************************************************************************** * * The following are new methods defined in the DEController. * ******************************************************************************/ - (int)bytesPerFrame; /* * Returns the number of bytes in one (channel-independent) frame of data */ - (int)playFrom:(int)startSample; - (int)playFrom:(int)startSample until:(int)stopSample; /* * Begins playback of the sound from the specified * (channel-independent) start sample. The second * method allows the caller to specify the length * of the selection to be played. */ - prepareToPlayFrom:(int)startSample; /* * Prepares playback of the sound from the specified * (channel-independent) start sample by offsetting * the soundStruct's data by the appropriate value. */ - (int)prepareToRecord; - prepareToRecord:sender; /* * Prepare the NeXT for recording by setting up the appropriate * data streams, loading DSP code, etc. When this is done, the * data begins streaming in and is sent to the delegate via the * dataBeingRecorded::: method (if implemented). The method * returns an error code. */ - (int)saveSound:(char *)savepath; - save:sender; /* * Displays a save panel for the user to specify a location where the * sound will be saved on disk. If the user clicks the save panel's * OK button, this method saves the sound and returns an error code. * Otherwise, this method returns -1. */ - (int)openSound:(char *)openpath; - open:sender; /* * Displays an open panel for the user to locate a sound saved on disk. * If the user clicks the open panel's OK button, this method opens the * sound and returns an error code. Otherwise, the method returns -1. */ - (int)setDspCode:(char *)file in:(char *)dir; /* * Sets the DSP code to be used for recording from the DSP. The variable, * "file", should be the filename of the code and may end in either ".lod" * or ".snd". The variable, "dir", should be the full path to the directory * where the code is located. If "dir" is set as the constant, APP_FOLDER, * the method looks for the code in the application's .app folder. */ - (char *)recordPath; - setRecordPath:(char *)fullpath; /* * Gets/sets the location for saving newly-recorded sounds. The variable, * "fullpath", should be a complete UNIX path with the ".snd" extension. * In addition, the record path should be located on the internal hard disk * since writing sound data to optical disk 'on the fly' is unreliable. */ - (int)startTrace; /* * This method initiates the "trace mode" of the DEController, whereby * data is constantly streamed to the delegate via the dataBeingRecorded::: * method. This method should not be called if the DEController is currently * not stopped. */ - (int)stopTrace; /* * This method stops the "trace mode" of the DEController. */ - setTimerInterval:(float)dt; /* * This method sets the interval for sending playback data to the * DEController's delegate. */ - (int)bytesRecorded; /* * This method returns the number of bytes actually written to * disk during a recording. */ /****************************************************************************** * * The following methods are used internally by the DEController for * messaging to the DERecorder object. See the DERecorder documentation * for details. * ******************************************************************************/ - streamPrepared:sender; - streamStopped:sender; - dataBeingProcessed:sender:(char *)data:(int)numbytes; @end @interface DEDelegate:SoundDelegate - playPaused:sender; - playResumed:sender; - recordReady:sender; - recordPaused:sender; - recordResumed:sender; - dataBeingPlayed:sender:(char *)data:(int)playedsamples; - dataBeingRecorded:sender:(char *)data:(int)datasamples; @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.