You are here: Symbol Reference > AudioSignal Namespace > Classes > TSignalIn Class
DSP Master VCL
ContentsIndex
PreviousUpNext
TSignalIn Class

Record data from an audio card.

AudioSignal_TSignalInAudioSignal_TSignalInAudioSignal_TSignalInAudioSignal_TSignalInAudioSignal_TSignalIn
Pascal
TSignalIn = class(TAudioSignal);

Use TSignalIn for recording of audio data. There are two ways to receive an audio stream from the component. One is via the Pull method, which is called each time a new buffer is filled once the processing has started. The Pull method is called only, if AutoPull property is True. The other method uses the OnBufferFilled event. In both cases the audio data stream is placed in Self. 

The component features two very important functions: Monitor and Trigger. Together with the double buffered processing, this functions make it possible to monitor a recording currently in progress and catch Trigger conditions, while the recording data is being streamed to disk. 

The audio driver requires at least two buffers. While it is writing in the first one, the user can copy data from the second one. When the first buffer is full, the driver starts to write in the second buffer and the user can copy data from the first one. This process is transparent to the user. When a new full buffer becomes available a Pull method will called, if AutoPull is True. If AutoPull is false and OnBufferFilled event is assigned this event will be called. If even the event is not assigned, then there will be no notification to the user when an audio buffer becomes full. The user can still call the Monitor function to obtain the latest data from the audio buffers. 

The Monitor function copies data from the (audio) buffers, before the buffer is full. This is possible by calling a special WINAPI function GetWavePosition, which returns the number of samples recorded so far. This allows TSignalIn component to compute where in the buffer is the sound driver currently putting the samples. The advantage of this approach is, that the user does not have to wait for the buffer to become full, before he gains access to the data within that buffer. This means, that the delay between the event (when the signal changes) and the time when the this event becomes visible on the screen can be very short. With FFT Properties, this delay can be less then 0.1 s. Such short delays are not possible when you have to wait until a buffer is full. 

Typically, a single buffer must be about 0.5 seconds long to prevent sample skipping. Alltogether there are usually 4 buffers: 4*0.5 = 2 seconds. This 4 buffers determine how long data blocks can be copied by the Monitor function. They can not be longer then 2 seconds in case of 4 buffers with each holding 0.5 seconds. FFT Properties uses a timer that calls the Monitor function. The clock of this timer is almost independent of the buffer size or recording parameters. 

Once the buffer gets full, it will not be displayed on the screen, because the Monitor function already did that part of the job. The job that the Monitor function can not do, is provide a steady continuous non-overlapping stream of data. This is what we get when buffers get full. We get non-overlapping blocks of data ready to be written to file (for example).. 

One question remains. Why not having just two buffers each 1 seconds long? Or maybe each of them 5 seconds long? That would not affect how Monitor function works or its updates or the update frequency of the charts. Buffers are processed in blocks. It is therefore better to have many small buffers, because whatever processing is followed (could be a filter or sound field effect) is broken down in to smaller pieces. If buffers would be processed in big pieces, the screen update might stop for the time of processing the block. This would result in jittering chart updates (The chart updates would be smooth for 5 seconds, then it would stop for 0.5 second and again smooth for 5 seconds...). 

The point of having many small buffers is to distribute the processing evenly across time. 

The Trigger function works in the same way as the Monitor function. The Trigger function calls the Monitor function to obtain the most recent data from the buffers. The call frequency must be high enough, so that during the time passed between two consequtive calls, the non-processed data in the buffers is not yet overwritten with the new data. Once a call is made, all the recorded samples currently in the audio buffers are checked, if they meet the trigger condition. Once the trigger condition is found, the appropriate data (block before trigger, after trigger etc..) is be copied to the local Data buffer (passed as a parameter to the function). When the next call is made to the Trigger function, it will continue to search for the next trigger condition. Once the next trigger condition is found, the Trigger function will overwrite the data obtained previously. In the DSP for MtxVec demo, the trigger is set to not overwrite the data, once a new trigger condition is found, unless the trigger has been reset. (That is why there is a reset button.) This button only sets a flag to false. The recording in the background is running continuously. 

Each time the trigger function is called, all the new data is processed, if the trigger condition is not found within that data. If the trigger condition is found, the data is not further checked from the trigger position on, until the next call is made. The trigger function remembers the position where it has stopped checking the data for the trigger condition and when the next call is made, it starts where it left off. 

If one full buffer is missed (4*0.5 = 2 seconds) there is a catchUps array which counts the number of such full buffer drops. This parameter is also displayed on the time signal chart on the "trigger" form of DSP for MtxVec demo. 

If the trigger condition is met for almost every sample, then the trigger could be reset 100 times per second and it would still not be enough to keep the pace with how quickly trigger conditions would be found, because the timer frequency will be lower then the frequency of trigger conditions found. With a timer set at 20Hz only 20 trigger conditions can processed per second. A typical practical application requires only one trigger reset per several seconds or more 

Normally, the user would reset the trigger and then wait until trigger condition is found (for example a few seconds). Once the data is acquired, the trigger can be reset again. 

Note that the Trigger function has to be called continuously with a timer whose frequency is high enough so that yet unprocessed buffers will not get overwritten with the new data and that the number of trigger conditions per second will be less then the timer frequency. 

The audio driver is working in the background in its own thread. When he is given 4 buffers, the recording will be running uninterrupted until the first buffer is full. When the first buffer is full, the driver sends a message to the window, designated for receiving audio driver messages, triggering an OnBufferFIlled event. Even if the app is stalled, the audio driver will still record until it fills all 3 remaining buffers and is sending a message to the window associated with the recording each time a buffer gets full. After all four buffers have been recorded and the application is still frozen, there are 4x OnBufferFilled requests in the message queue of the application. If the application unfreezes at least a few miliseconds before the last buffer is full, and it is able to process all pending requests within that short time, the recording will continue uninterrupted. If the total length of all four buffers is 2 seconds, that means that application can be completely frozen for about 1.5- 1.8 seconds, before the recording will be interrupted. 

If the Monitor function is called with a frequency of 20Hz, then after 1.5 seconds there would be 30 requests pending to be processed. If it takes about 20% of the CPU to process 20 requests per second, that means that it takes only 0.2 seconds for the CPU to do its work and the app could be halted for 1.8 seconds, before the recording would be affected. If the total size of all recording buffers is increased to 10 seconds then it would take 9 seconds of a complete application freeze, before the recording would stop. The buffers should be short and there should be many of them, to distribute the processing across time, if longer total audio buffer length is desired.

Copyright (c) 1999-2025 by Dew Research. All rights reserved.
What do you think about this topic? Send feedback!