GUS Programmer's Digest Wed, 29 Sep 93 0:07 MDT Volume 4: Issue 18 Today's Topics: How to avoid a recording pitfall Standard Info: - Meta-info about the GUS can be found at the end of the Digest. - Before you ask a question, please READ THE FAQ. ---------------------------------------------------------------------- Date: Tue, 28 Sep 1993 14:26:37 -0400 From: davidm@marcam.com (David MacMahon) Subject: How to avoid a recording pitfall Message-ID: <9309281827.AA04507@ottawa.marcam.com> Hello fellow GUS programmers, This is a somewhat long message about a recording problem (best described as distortion or noise) that I have in my program (GUSDELAY). I have found the phenomenon I believe is the cause of the problem, but I have not yet been able to test my theory. I have also thought about how to solve this problem and have come to the conclusion that while there is no way to solve it totally, it can be minimized so that (hopefully) it is negligible. I'm pretty sure that this phenomenon exists for any program that attempts to do continuous recording from the GUS. If anyone can prove me wrong, please do. The problem I was experiencing was distortion (noise) in the recorded data. I had attributed this to missing samples until I noticed that the problem got worse at low sampling frequencies! I connected an o'scope to the record DMA request line (DRQ) to see what was happening. I recorded in mono with a sampling frequency of 7015 Hz (sample time of 143 uS). I measured the time between DMA requests to be about 280 uS (I use a 16 bit DMA channel so in mono the rate gets halved). So far so good. Then I noticed that the time between the last DMA request of one buffer and the first DMA request of the next buffer was only about 220 uS! In other words, everytime I started recording into the next buffer I would start to sample the input at the desired frequency, but the sampling started 60 uS before it should. The impact of this is extra significant in GUSDELAY because the buffers are only 32 bytes long, so this 60 uS error occurred every 32 samples (4562 uS). For a 1000 Hz input signal, 60 uS == 21 degrees. Here is an attempt to represent this ascii-graphically: 0 0 0 0 0 0 01 1 1 1 1 1 1 1 1 1 1 1 1 1 1 10 0 0 0 <-Buffer number 9 A B C D E F0 1 2 3 4 5 6 7 8 9 A B C D E F0 1 2 3 <-DMA number ^^^ ^^ 286 uS 220 uS NOTE: There are sixteen 16-bit DMA transfers per 32 byte buffer. The average sampling frequency is (32*1000000/(32*143-60)) (Hz). This works out to 7086 Hz. This is 1.0% higher than the programmed frequency. If I switch to a 32000 byte buffer, the equation becomes: Average Sampling Frequency = (32000*1000000/(32000*143-60)) (Hz) This works out to 6993 Hz. This is 0.3% lower than the programmed frequency. This is clearly more desireable. Not only is the average sampling frequency (ASF) closer to the programmed sampling frequency (PSF), the irregularity in sample times happens every 32000 samples and not every 32 samples. It is also interesting to note that when I set up USS8 to do mono recording at 7015 Hz, it would always display 6993 Hz as the sampling frequency. I never knew where the 6993 figure came from, but now I do. It may seem strange that the ASF is lower than the PSF when the sampling is "early". This is due to integer math and the fact that the sample time is not exacly 143 micrseconds. At higher sampling frequencies, when (if) interrupt latency becomes a factor, the ASF may actually be slower than the PSF. A better formula for the ASF would be: ASF = N*1000000/((N-1)*Ts+Ti+Ta) (Hz) Where: N = buffer size Ts = Microseconds per sample at the PSF Ti = Interrupt latency time (in microseconds) This is the time from the interrupt to the time the control registers on the GUS get hit. Ta = The acquisition time of the first sample (in microseconds) Ti varies from system to system and from program to program (depending on how the interrupt handler is structured) and could be a configuration option of applications that desire a high level of precision. Ta is probably a spec of the GUS itself. I will try to measure this as accurately as possible, but if anyone (from Forte or AG) knows this value please share it with us!!! This phenomenon also explains something that I complained about in my first message regarding simultaneous playback/record (see GUS Programmer's Digest V3 #11, "Simultaneous recording/playback works!!!"). In that message I referred to a strange behavior that I called "voice creep". My delay would shrink over time until the voice passed the point where new data was being written. I didn't know what was causing it, but worked around the problem by regularly setting the voice back to where it should be. Now it is apparrent that my ASF was slower than the PSF and I was using the PSF as the playback frequency. Well, that's all for now. Future versions of GUSDELAY will implement a larger recording buffer and will also use the ASF as the playback frequency instead of the PSF. Dave David MacMahon Systems Administrator davidm@marcam.com <---New address, use this one davidm@opl.com <---Old address, don't use this one ------------------------------ End of GUS Programmer's Digest V4 #18 ************************************* To post to tomorrow's digest: To (un)subscribe or get help: To contact a human (last resort): FTP sites: archive.epas.utoronto.ca pub/pc/ultrasound wuarchive.wustl.edu systems/msdos/ultrasound Hints: - Get the FAQ from the FTP sites or the request server. - Mail to for info about other GUS related mailing lists (UNIX, OS/2, GUS-MIDI, etc.)