Daqarta
Data AcQuisition And RealTime Analysis
Scope  Spectrum  Spectrogram  Signal Generator
Software for Windows Science with your Sound Card! 

The following is from the Daqarta Help system:

Features:OscilloscopeSpectrum Analyzer 8Channel

Applications:Frequency responseDistortion measurementSpeech and musicMicrophone calibrationLoudspeaker testAuditory phenomenaMusical instrument tuningAnimal soundEvoked potentialsRotating machineryAutomotiveProduct testContact us about


Arb_From_Equation Macro MiniApp
Introduction:Arb_From_Equation is one of the Macro Examples and MiniApps included with Daqarta. It allows you to create an Arb waveform file from an equation that you provide, or modify from one of the included examples. An Arb file normally holds a single complete cycle of the waveform you want to create, such that when the Daqarta Generator steps through it repeatedly you get a continuous wave at whatever Tone Frequency you have chosen. However, you are not limited to "normal" continuous waves like sine, triangle, or square; you can use any arbitrary shape that you can define by equations. (See Arb_From_List for another way to create Arb files.) The only requirement is that the equation must produce a series of output values that correspond to increasing Xaxis steps: The output can't move backwards in time (or on the screen), so the waveform can't have undercuts. That means, for example, that you can't draw a complete circle on the screen with a single output channel... but you can draw the top half with one channel and the bottom with another. (See the Circle wave discussion, below.) But producing unusual waveforms is only one use of Arb files. Arbs can also be used as modulator sources for other streams, such as to create waves with arbitrary amplitude or frequency changes. They can serve as lookup tables, such as the Expnote.DAT table of musical note frequency values that can be randomly selected to modulate a stream that creates music. (See the Composer.GEN discussion for an example.)
Operation:When you run Arb_From_Equation it loads a Generator setup called ArbTest.GEN and fills a Memory Arb (MemArb) with samples computed from the parameters and equation in the macro code. The MemArb is used to create a repeating waveform, with one full cycle displayed on the screen. Note that it may take a few seconds for the full wave to appear; you'll see a "Creating Arb in Memory..." message during this time. Arb_From_Equation then opens a standard Windows Save As dialog that prompts you for the name of a file to save the Arb as. By default it will be a .DAT file in Daqarta's User_Data folder, but you can navigate elsewhere, or change the file type via the Save as type dropdown control. You can enter any file name you want, but starting it with Arb_ will make it easier to distinguish from other files in the same folder. You can hit Cancel if you aren't ready to save the file. Note that at this point the Generator is set to maximum loudness, but muted so you don't have to listen to it. The Y axis thus shows the fullscale output values; the range will be +/1000 mV (1 V) unless you have done a FullScale Range calibration, in which case it will be +/ the calibration value. You can use the cursor readouts to check the values at various points on the waveform. You can then modify the code and rerun it until you are satisfied with the result.
Setting Arb File Size:By default, the created Arb will be 16K (16384) samples, the largest size Daqarta supports, for maximum resolution. This size is set via the UK=16 line near the start of the macro code. You can change it to 1, 2, 4, or 8 instead to get smaller files.
Waveform Width Control:The W=100 line sets the Width of the created wave in percent; assuming that your equation is written to produce one full cycle of the waveform (as in the examples provided), reducing W will compress the waveform into a smaller percentage and fill the remainder with zeros. For example, the Arb_Sine50.DAT file used W=50 to squeeze one cycle of the sine into the first half of the Arb. If you use this Arb with Tone Freq set to 1000 Hz, for example, you'll get a spectrum with a peak at 1000 (the expected fundamental), plus a peak at 2000 (since the sine wave takes only half the Arb cycle it is twice its frequency), plus components at 3000, 5000, 7000, and all odd multiples of the fundamental. This provides a controlled distortion that adds rich harmonics but is less harsh than other types of distortion such as clipping. This richness is especially noticeable (and pleasant) at low tone frequencies. You can modify the code to create more than one cycle of the sine wave (or any waveform) in the Width interval. That's especially easy for the sine: Just multiply the contents of the parentheses by the desired number of cycles. For example, the normal sine equation is MemArbV[UA]=K*sin(2*pi*UA/US), so to get UC cycles use MemArbV[UA]=K*sin(UC * 2*pi*UA/US).
Equation Scripts For Included Arbs:Below are code examples for the Arb files included with Daqarta. You can modify them for your specific needs, or use them as templates to create Arbs from completely different equations. To use each section below, copy and paste it to replace the section in Arb_From_Equation designated between ;====... comment lines. Preceding each equation section, the initial part of Arb_From_Equation sets common variables that all equations use. K=32767, which is the maximum positive output value of the sound card. It is used as a scaling factor so that (for example) a sin() function with a +/1.00 range will extend over the full range of the sound card. UN is the number of samples in the Arb, either 1024, 2048, 4096, 8192, or 16384 (default). It is obtained via UN=MemArbV?N after creating the MemArb using MemArbV#N=UK, where UK=16 (or 1, 2, 4, or 8) was given at the start of Arb_From_Equation to set the size. W is the Width percentage, as described in the Waveform Width Control section above. It defaults to W=100 and can never be greater than 100. US is set via US=W/100 * UN, giving the number of output samples in the active Width region. Variable UA starts at 0, and is used as the output sample index. Each equation section typically consists of one or more WHILE/WEND loops that ultimately step from index 0 to US1 to create the active output samples. Since the MemArb was filled with all zeros when created, this leaves any remaining samples at 0 if Width is less than 100 percent. Since each equation section must produce one complete waveform cycle in US samples, each step is 1/US wide and the current step is UA/US. The Sine Wave equation section below shows how all these variables work together in a typical case. Note that if you want to create an Arb that is the sum of multiple waves or calculations, you should avoid the seeminglyobvious approach of creating a single full wave over all UN samples of the MemArb, then creating UN additional samples and adding them. Instead, make only a single pass through the MemArb, with each sample being the sum of all the component values at that point. (In other words, the MemArb should only appear on the left side of the expression.) The reason for this is that a MemArb is standard 16bit waveform data, whereas the calculations are much higher resolution (32bit for integers like UN, full 80bit floating point for variables AZ). If you compute the waves separately, any roundoff to 16bit will accumulate. See the Sine Series section below for the recommended approach.
Sine Wave:There's never any need for a plain sine wave Arb when using Daqarta with a sound card, since Sine is one of the standard Daqarta Generator wave types. However, the DaquinOscope macro miniapp uses an Arduino USB board instead of a sound card, and can't use the Generator to create waveforms directly. Instead, it uses the Wave Oscillator function of the DaqPort Arduino code to output a waveform that is first loaded into Arb7 of the Generator and then uploaded to the Arduino as an array of 256 or 1024 8bit samples. These are then output in a repeating sequence on 8 simultaneous digital output pins for conversion to an analog waveform by means of a simple R2R ladder DAC. The Wave Oscillator code in DaqPort takes care of stepping through the samples at the proper rate to produce the wave at the desired frequency and phase. The Arb_Sine.DAT file included with Daqarta was created using the Sine Wave code below. DaquinOscope uses the Port#a7=$(hF0) + "o" or Port#A7=$(hF0) + "O" Bulk Data Write commands to automatically convert the Arb values to the 0255 range needed, and decimate to 256 or 1024 samples, respectively, before uploading to the Arduino. Additionally, the Sine Wave code below can be used (with a sound card or DaquinOscope) as the basis for other equations of your own, or for creating "compressed" waveforms with null padding as discussed under Operation  Waveform Width Control, above. The Arb_Sine50.DAT file included with Daqarta was created using the code section below, with W=50 (near the start of Arb_From_Equation) instead of the default W=100.
;==== Sine Wave =========================== WHILE.UA=<US MemArbV[UA]=K*sin(2*pi*UA/US) ;Sine wave, scaled to fit in Width UA=UA+1 WEND. ;==========================================
Rectified Sines:
HalfWave Rectified Sine:The following code produces a sine wave with only the positive halfcycle present; the negative half is replaced with nulls. This is the waveform created by a single diode rectifier acting upon a sine wave source, as in a simple power supply. Arb_HalfRectSine.DAT was created with this code.
Note that the code is identical to the normal Sine wave code above, except that the limit of the WHILE loop has been cut in half so that only the first half of the waveform is created. ;==== HalfWave Rectified Sine ============== WHILE.UA=<US/2 ;NOTE the /2 is only difference from Sine MemArbV[UA]=K*sin(2*pi*UA/US) ;Halfcycle of sine UA=UA+1 WEND. ;===========================================
FullWave Rectified Sine:This code is identical to the normal Sine wave code given earlier, except that it uses the {\b abs()} function to take the absolute value. This "flips up" the negative halfcycle to produce a fullwave rectification such as might be found in a power supply using a 4diode bridge, or 2 diodes with a splitsecondary transformer. Arb_FullRectSine.DAT was created with this code.
;==== FullWave Rectified Sine ============== WHILE.UA=<US MemArbV[UA]=abs(K*sin(2*pi*UA/US)) UA=UA+1 WEND. ;==================================================
Sine Series:This section includes code for various multisine series. The Ramp (Sawtooth), Square, and Triangle Series approximate their namesake waveforms using as many components as you desire. This is controlled by changing a single parameter; 4 and 8component series examples are shown for Ramp and Square waveforms, but the Triangle series converges so quickly that only a 4component example is shown. Note that these "standard waveform" series are also discussed in Making Waves via Sine Wave Synthesis, which uses a separate Generator stream for each sine wave and is limited to 4 terms (although 8 are possible using the MultiChannel Output Controls, even if you only have a 2channel sound card.) Finally, Equal Amplitude Sine Series discusses special test tone complexes, and includes spectra as well as waveform examples. Note: With all of these series, you use Tone Freq to set the fundamental frequency of the Arb wave. (Even if the fundamental is not actually included, as can be the case in the Equal Amplitude series.) Any harmonics will therefore be multiples of that fundamental, and can easily exceed the Nyquist frequency (half the sample rate) and thus be aliased to lower frequencies. (Try the Aliasing Demonstration to see this in action.) To prevent this, keep the product of the Tone Freq and the highest harmonic number below half the sample rate. For example, with the 4component Arb_Sine4Square.DAT discussed in the Sine Square Series section below, the highest harmonic is the 7th. With the default sample rate of 48000 Hz, that means that Tone Freq must be less than 48000 / (2 * 7) = 3428.57 Hz. But for the 8component Arb_Sine8Square.DAT the highest harmonic is the 15th, so the maximum Tone Freq would be only 48000 / (2 * 15) = 1600 Hz.
Sine Ramp (Sawtooth) Series:The Sine Ramp Series approximates a ramp (sawtooth) waveform using a series of sines. The QM parameter sets the number of sine components to be used. The series consists of a fundamental (which would be set by Tone Freq when using the Arb) followed by a series of harmonics: 2nd, 3rd, 4th, etc. The amplitude of each component is scaled according to its reciprocal, so the 2nd harmonic amplitude is half the fundamental, the 3rd harmonic is onethird, and so forth. We further cut each component in half, including the fundamental, using K/(2*QN) instead of just the K/QN implied above. Otherwise the components add together to be greater than +/100% at the positive and negative peaks, causing clipping distortion. Note that some math references (such as Wikipedia) scale by 2/pi, which would be equivalent to K*2/(pi*QN) here. That would work for a 4component series, but would cause clipping with 5 or more components due to Gibbs phenomenon. (See also the Sine Square Series below.) The more harmonics that are included, the better the approximation to a ramp. The examples here are for a ramp that starts high and gradually ramps down, which would be equivalent to the normal Ramp Wave using Ramp Rise set to 0. You can easily change that to a ramp that starts low and ramps high (Ramp Rise = 100%) by changing the sign of K in the inner WHILE loop from '+' to '' as in: X=XK/(2*QN)*sin(QN*2*pi*UA/US) Arb_Sine4Ramp.DAT was created using QM=4 for a 4component approximation:
Arb_Sine8Ramp.DAT was created using QM=8 for an 8component approximation:
;==== Sine Ramp Series ==================== QM=4 ;Number of components WHILE.UA=<US QN=1 ;Start with fundamental X=0 WHILE.QN=<(QM+1) X=X+K/(2*QN)*sin(QN*2*pi*UA/US) QN=QN+1 WEND. MemArbV[UA]=X UA=UA+1 WEND. ;==========================================
Sine Square Series:The Sine Square Series approximates a square waveform using a series of sines. The QM parameter sets the number of sine components to be used. The series consists of a fundamental (which would be set by Tone Freq when using the Arb) followed by a series of odd harmonics only: 3rd, 5th, 7th etc. The amplitude of each component is scaled according to its reciprocal, so the 3rd harmonic amplitude is onethird the fundamental, the 5th harmonic is onefifth, and so forth. Note that some math references (such as Wikipedia) also scale by 4/pi, which would be equivalent to K*4/(pi*QN) here. That sets the amplitude of the resultant wave to K, the fullscale range of the sound card. However, the amplitude they are computing is the flat top and bottom of an ideal square wave. But the sine series approximation exhibits an effect known as Gibbs phenomenon, which causes pseudo"ringing" at each vertical transition. This produces a series of peaks that rise above and below the horizontal parts of the waveform. (See images below.) If the 4/pi scaling set the horizontal to be 100% of the available range, then the Gibbs peaks would attempt to exceed that, and thus cause distortion when they are clipped off. The more harmonics that are included, the better the approximation to a square. Note, however, that the Gibbs peaks are always present with any finite number of terms. Arb_Sine4Square.DAT was created using QM=4 for a 4component approximation. (See this waveform in action with a frequency sweep in the Aliasing Demonstration.) One cycle of the wave looks like this:
Arb_Sine8Square.DAT was created using QM=8 for an 8component approximation:
;==== Sine Square Series ========= QM=4 ;Number of components WHILE.UA=<US QN=1 ;Start with fundamental X=0 WHILE.QN=<(QM+1) X=X+K/(2*QN1)*sin((2*QN1)*2*pi*UA/US) QN=QN+1 WEND. MemArbV[UA]=X UA=UA+1 WEND. ;==================================
Sine Triangle Series:The Sine Triangle Series approximates a triangle waveform using a series of sines. The QM parameter sets the number of sine components to be used. The series consists of a fundamental (which would be set by Tone Freq when using the Arb) followed by a series of odd harmonics only: 3rd, 5th, 7th etc. Unlike the Sine Square Series above, each odd harmonic is scaled according to the square of its reciprocal, and the signs of the terms alternate. So the 3rd harmonic is (1/3)^2 or 1/9 of the fundamental and is subtracted, while the 5th harmonic is (1/5)^2 or 1/25 of the fundamental and is added, etc. The alternating signs of the terms are handled via a factor QI, which starts out as +1 for the fundamental, and is negated for each subsequent harmonic. The fullscale range value K is adjusted by a scale factor of 8/pi^2 to bring the overall series amplitude close to the original fullscale range. The more harmonics that are included, the better the approximation to a triangle. However, unlike the above Ramp and Square series, the triangle converges very quickly. Arb_Sine4Triangle.DAT was created using QM=4 for a 4component approximation. Compared to even the 8component Ramp and Square series, this is a much better fit to its target waveform:
;==== Sine Triangle Series ========= QM=4 ;Number of components K=K*8/pi^2 ;Adjust fullscale factor WHILE.UA=<US ;Do all sampled QN=1 ;Start with fundamental X=0 ;Accumulate sample value QI=1 ;Alternating sign factor WHILE.QN=<(QM+1) ;Do all harmonics X=X+QI*K/(2*QN1)^2*sin((2*QN1)*2*pi*UA/US) QN=QN+1 ;Next harmonic QI=QI ;Flip sign for next harmonic WEND. ;Next harmonic MemArbV[UA]=X ;Save sample value UA=UA+1 ;Next sample WEND. ;==================================
EqualAmplitude Sine Series:The EqualAmplitude Sine Series produces QM multiple tones of equal amplitude, which are also equally spaced above an adjustable initial tone. The tones are part of a harmonic series whose fundamental is given by the Tone Freq when using the Arb, but that fundamental is not necessarily included as a component of the series. In fact, the series starts with the QFth harmonic. Furthermore, the spacing of the remainder of the QM tones in the series may be at steps that are some multiple QS of Tone Freq. This series is typically used to create a particular spectral band of discrete tones for test purposes, as an alternative to bandlimited noise testing. Here we give up continuous spectral coverage over the band in exchange for nonrandom behavior and stable amplitudes, with sharplydefined band edges and component frequencies. You can control the number and density of those components via the QM and QS parameters. Note that since the QM components have equal amplitudes that start out inphase and can sum together to large peaks, each of them has been reduced to 1/QM of the fullscale range to prevent clipping. Thus, as you add more components, their levels get smaller. But the resulting levels are still higher than the equivalent with a continuous noise band, for exactly the same reason: The noise band must also guard against clipping at the worstcase instantaneous random waveform peak. If you have a lot of components and don't really need them to all start at the same phase, it is possible to adjust their individual phases to minimize resulting peak heights, and then boost the overall waveform level above the usual K/QM. See the "Phase Experiments" section of the Missing Fundmental macro miniapp for more details and references. The Arb_Sine543.DAT example has 5 components (QM=5) starting at 4 times the Tone Freq (QF=4) with a spacing of 3 times the Tone Freq (QS=3). The waveform of a single cycle looks like this:
With a 1 kHz Tone Freq the spectrum has tones at 4, 7, 10, 13, and 16 kHz:
The equalamplitude series approach was used in the Missing Fundmental macro miniapp, except that had separate signal streams which were individually controlled. The Arb approach is much simpler: You just set Tone Freq to the (missing) fundamental frequency. You can then create bursts or sweeps as desired. As in the miniapp, you can alternate between bursts having different harmonic structures. With the Arb approach you do this using a different Arb in each stream, with burst cycles set the same but with a lag in one of them. The Arb_Sine521.DAT is a good example of a "missing fundamental" Arb. It has 5 components (QM=5) starting at 2 times the Tone Freq (QF=2) with a spacing equal to the Tone Freq (QS=1). The waveform of a single cycle has this shape:
With a 1 kHz Tone Freq the spectrum has tones at 2, 3, 4, 5, and 6 kHz, all of which are harmonics of the missing 1 kHz fundamental:
;===== EqualAmplitude Sine Series ===== ;MultiSine wave with adjustable start and spacing QM=5 ;Number of components QF=4 ;Start (* Tone Freq) QS=3 ;Spacing (* Tone Freq) WHILE.UA=<US QN=1 X=0 WHILE.QN=<(QM+1) X=X+(K/QM)*sin((QF+(QN1)*QS)*2*pi*UA/US) QN=QN+1 WEND. MemArbV[UA]=X UA=UA+1 WEND. ;=======================================
Multiple Sine Wave Harmonics:This is similar to the above EqualAmplitude Sine Series, except that it uses only integer harmonics and allows independent amplitudes. It was used to create Arb_Fake_Vowel.DAT, which is an optional waveform for the !Spooky.GEN SciFi Theremin Simulator. It sounds vaguely human in that setup, especially when the pitch is changing between notes. Arb_Fake_Vowel is also used by Machines.GEN to create a harmonicrich lowfrequency "power hum" for a Halloween "Mad Scientist" laboratory display. The amplitude of each harmonic is specified in the corresponding element of Buf0: The fundamental is in Buf0[1], the second harmonic in Buf0[2], the third in Buf0[3], etc. QM is then set to the number of components. The code computes all components from 1 to QM, so if you want to skip a harmonic you must set its Buf0[] amplitude to zero. The following example for Arb_Fake_Vowel.DAT uses the fundamental plus the second and third harmonics. Note that in general the sum of the component amplitudes should not exceed 1.00 to insure there is no clipping, but this example totals 1.15 without clipping.
;==== Multiple Sine Wave Harmonics ======== Buf0[1]=0.5 ;Fundamental amplitude Buf0[2]=0.25 ;2nd harmonic amplitude Buf0[3]=0.40 ;3rd harmonic amplitude QM=3 ;Number of components WHILE.UA=<US QN=1 ;Start with fundamental X=0 WHILE.QN=<(QM+1) X=X+K*Buf0[QN]*sin(QN*2*pi*UA/US) QN=QN+1 WEND. MemArbV[UA]=X UA=UA+1 WEND. ;=================================
Triangle Wave:As for the Sine Wave code above, there is never any need for a plain triangle wave Arb when using Daqarta with a sound card, since Triangle is one of the standard Daqarta Generator wave types. But the DaquinOscope macro miniapp works with an Arduino USB board instead of a sound card, and uses Arb files uploaded to the Arduino to create waveforms as described under the Sine Wave section. The Arb_Triangle.DAT file included with Daqarta was created with the Triangle Wave code below to provide a plain triangle wave for this purpose. Additionally, this code can be used as the basis for other equations of your own, or for creating "compressed" waveforms with null padding as discussed under Operation  Waveform Width Control, above. Arb_Triangle50.DAT was created with this code, using W=50.
;=== Triangle Wave ======================== US=US/4 S=K / US WHILE.UA=<US MemArbV[UA]=UA * S UA=UA+1 WEND. WHILE.UA=<3*US MemArbV[UA]=2*K  (UA * S) UA=UA+1 WEND. WHILE.UA=<4*US MemArbV[UA]=(UA * S)  4 * K UA=UA+1 WEND. ;============================================
Ramp Wave:As for the Sine Wave and Triangle Wave code above, there is never any need for a plain ramp wave Arb when using Daqarta with a sound card, since Ramp is one of the standard Daqarta wave types. In fact, the Daqarta Ramp dialog allows easy change of the Ramp Rise (otherwise done via R=75 in the code here), as well as a staircase option and selection of either Phase or Slope modulation types when used with Daqarta's standard Phase Modulation option. However, the DaquinOscope macro miniapp works with an Arduino USB board instead of a sound card. Its Wave Oscillator function can create waveforms using Arb files uploaded to the Arduino as described under the Sine Wave section. The Arb_Ramp100.DAT file included with Daqarta was created with R=100 in the Unipolar Ramp Wave code below to provide a plain 0100% ramp wave for this purpose. Also, Daqarta's Ramp wave doesn't have a builtin Width option for creating "compressed" waveforms with null padding as discussed under Operation  Waveform Width Control, above. Arb_75Ramp50.DAT was created with this code, using W=50 together with the default R=75 here. Note that this wave is unipolar, starting at 0 and rising to 100%, while the standard Generator Ramp wave is bipolar, starting at 100% and rising to +100%. See the Bipolar Ramp Wave code, following, to create compressed bipolar waveforms for sound card use.
;===== Unipolar Ramp Wave ================= R=75 ;Ramp rise percent S=K / (US * R/100) WHILE.UA=<US * R/100 MemArbV[UA]=UA * S UA=UA+1 WEND. UB=UA S=K / ((1R/100) * US) WHILE.UA=<US MemArbV[UA]=K  ((UAUB) * S) UA=UA+1 WEND. ;========================================== The following Bipolar Ramp Wave code was used to create the Arb_Ramp_Bipolar100.DAT file included with Daqarta. Note that R=100 means that with the default W=100 this will create a standard 100% Generator Ramp that starts at 100% and rises to +100%. ;===== Bipolar Ramp Wave =================== ;NOTE that the baseline is 100%, not 0 as ;for Unipolar Ramp Wave. R=100 ;Ramp rise percent S=2 * K / (US * R/100) WHILE.UA=<US * R/100 MemArbV[UA]=K + UA * S UA=UA+1 WEND. UB=UA S=2 * K / ((1R/100) * US) WHILE.UA=<US MemArbV[UA]=K  ((UAUB) * S) UA=UA+1 WEND. UB=MemArbV[UA1] WHILE.UA=<UN MemArbV[UA]=UB UA=UA+1 WEND. ;==========================================
Square Wave:As for Sine, Triangle, and Ramp above, there's rarely any need for a plain square wave Arb like the included Arb_Square.DAT, since Square is one of the standard Daqarta wave types. And unlike other wave shapes, there is no need for a special Square Arb for the DaquinOscope macro miniapp used with an Arduino board; DaquinOscope standard oscillators (unlike the special Arbbased Wave Oscillators) produce square waves by default. However, the Square Wave code below can be used as the basis for other equations of your own, or for creating "compressed" waveforms with null padding as discussed under Operation  Waveform Width Control, above. The Arb_Square50.DAT file included with Daqarta was created using this code, with W=50 (near the start of Arb_From_Equation) instead of the default W=100:
For normal square waves, however, there is another reason to favor the builtin Square over an Arb version: Edge sharpness at low frequencies. The standard Square using Snap mode has edges that always transition in a single sample, although there will be some amount of edge jitter except for particular frequencies. In Interpolate edge mode, the standard Square has far less jitter, by using softer edge transitions that may take up to 2 samples. On the other hand, the Arb approach has minimal jitter (at least with the Arb set to Interpolate instead of Round or Step), but at frequencies less than a few Hz the transitions will be spread out over multiple samples. That's because the Arb just does an ordinary overall waveform interpolation, unlike the edgeonly Square Interpolate. The image below shows Arb_Square.DAT at a Tone Frequency of 1 Hz, with Trigger Delay and XAxis eXpand set to show an expanded version of a falling edge. The transition takes 4 samples, although you only see two obvious kinks because the central region is on a straightline section of the interpolation:
;======= Square Wave ====================== WHILE.UA=<US/2 MemArbV[UA]=K UA=UA+1 WEND. WHILE.UA=<US MemArbV[UA]=K UA=UA+1 WEND. ;===========================================
Pulse Wave:As with the above Square wave, Pulse is one of the standard Daqarta wave types. In fact, the Pulse dialog allows much more control than this simple code, which just produces a single positive pulse whose width is set via the W parameter. (The Pulse dialog allows two separate adjacent pulses with independent widths, levels, and polarities, as well as adjustable baseline and different width/modulation modes.) Instead, consider this simple code as a starting point for more advanced pulse creation. Note that if W=100 the pulse will stay high for the full cycle, resulting in a constant fullscale DC waveform. Since standard sound cards block DC, there will be no output at all. (True, you could use this to provide a DC modulation source, but you can do that simply by using the builtin Sine wave with Phase set to 90 degrees.) Arb_Pulse50.DAT was created with this code, using W=50. This gives a positiveonly square wave output. Again, since sound cards are ACcoupled, this is only useful as a modulation source. However, the DaquinOscope macro miniapp uses an inexpensive Arduino board to acquire DC data, and has an optional wavetable oscillator that produce arbitrary output waveforms. This or the following fullscale pulse will indeed produce DC pulses.
;======= Pulse Wave ======================== ;NOTE that if W=100 this just gives constant K level WHILE.UA=<US MemArbV[UA]=K UA=UA+1 WEND. ;===========================================
FullScale Pulse Wave:This is just like the above Pulse Wave, except that instead of a fullscale positive pulse that returns to a baseline of zero, this returns to fullscale negative. Also as above, this could have been done with the Pulse that is one of the standard Daqarta wave types, just by adjusting the zero level in the Pulse dialog, so consider this as a code example. Likewise, if W=100 the pulse will stay high for the full cycle, resulting in a constant fullscale DC waveform. Arb_FSPulse25.DAT was created with this code, using W=25 to produce a pulse that is high for 25% of the cycle.
;======= FS Pulse Wave ====================== ;NOTE that if W=100 this just gives constant K level WHILE.UA=<US MemArbV[UA]=K UA=UA+1 WEND. WHILE.UA=<UN MemArbV[UA]=K UA=UA+1 WEND. ;============================================
Tangent Wave:This code was used to create Arb_Tan.DAT, which is a plot of the tangent function over one full circle. Note that the tangent is discontinuous at pi/2 and 3*pi/2 radians, where it goes from positive to negative infinity. Since this would be awkward to try to reproduce with a sound card that is limited to +/32767, the waveform has been scaled down by a factor of 128. Feel free to experiment with other scale factors depending on your needs.
;======= Tan Wave =========================== ;NOTE that this has two peaks per cycle K=K/128 ;Reduce scale factor for less peak clipping WHILE.UA=<US MemArbV[UA]=K*tan(2*pi*UA/US) UA=UA+1 WEND. ;============================================
HalfTangent Wave:As above, but Arb_HalfTan.DAT produced with this code only covers half of a full circle by using tan(pi*UA/US) instead of tan(2*pi*UA/US). This give a single biphasic +/ fullscale spike at the center of the waveform (pi radians), instead of narrower spikes at pi/2 and 3*pi/2.
;======= Half Tan Wave =========================== ;As above, but single peak per cycle K=K/128 ;Reduce scale factor for less peak clipping WHILE.UA=<US MemArbV[UA]=K*tan(pi*UA/US) UA=UA+1 WEND. ;============================================
Gaussian Wave:The Gaussian curve describes what is known as a 'normal' distribution in statistics. It is the standard example of a "bellshaped curve". The code included here is for a 'standardized' version, in which the central peak is always unity (full scale here). The standard deviation D adjusts the width of the peak, with the default 1.00 producing tails that are 0.0072 (236 counts out of the fullscale 32767 counts). This was used to create the included Arb_Gauss.DAT file.
If you set D=0.70 instead, the tails will be 0.00003, or one count out of 32767. The width of the peak at halfmaximum (FWHM) as a fraction of the total width is found by FWHM = 0.375 * D. ;======= Gaussian =========== ;With D=1.00, tails = 0.0072 ;With D=0.70, tails = 0.00003 ;Central peak always 1.000 (Full scale) M=0 ;Mean = 0 D=1.00 ;Standard Deviation D=D / (2 * pi) ;Working value C=sqrt(2 * pi) ;0.3989 K=K * C WHILE.UA=<US X=(UA(US/2)) / US Z=(X  M) / D MemArbV[UA]=K * exp(Z^2 / 2) / C UA=UA+1 WEND. ;==============================
Lorentz And Derivative:
Lorentz:The Lorentz or Lorentzian distribution is also known as a Cauchy distribution. It is similar to a Gaussian in that it is a "bellshaped curve" tapering from a central peak. The simplified equation is Y=1/(X^2 + 1), but we'd like to control the width of the peak, the way standard deviation does for the Gaussian. We use P as the width of the peak at halfmaximum height (FWHM), and working variable G=P / 2. The revised simplified equation then becomes Y=G / (X^2 + G^2). Note, however, that this formulation is not normalized: The peak height changes with width. The code below keeps a constant fullscale height using Y=G^2 / (X^2 + G^2). Arb_Lorentz_8th.DAT was created with the default P=0.125, which gives a width that is 1/8 of the full Arb cycle:
;======= Lorentz ================ P=0.125 ;Width of peak at half height G=P / 2 WHILE.UA=<US X=(UAUS/2)/US MemArbV[UA]=K * G^2 / (X^2 + G^2) UA=UA+1 WEND. ;==============================
D_Lorentz:The derivative of the Lorentz function is a biphasic pulse. The 'standard' equation is Y=2 * X / (X^2 + 1)^2. Using the same width control P from the above raw Lorentz, along with working variable G=P / 2, the derivative would be Y=2 * X / (X^2 + G^2)^2. However, as with the raw Lorentz, we also normalize to keep constant fullscale peak heights. The normalized formula is Y=2 * X * G^3 / (X^2 + G^2)^2. Note that although the peak heights are normalized, this does not automatically provide for a useful repeating waveform. The problem is that unless the width is kept very small (P=0.017 or less), the starting amplitude and the ending amplitude are different, which would result in an abrupt step at the end of each cycle. Below are plots for various P values:
The Arb_D_Lorentz.DAT file is shown as the green curve for P=0.017. The tails are both zero, so there is no step. If the fullscale output range is +/1000 mV, the steps for the other P values are: P Step, +/mV 0.500 247 0.250 42.6 0.125 5.8 0.017 0.0 ;======= DLorentz ================ P=0.017 ;Width of raw Lorentz peak G=P/2 K=K / 0.6495 ;Scaling for fullscale peaks WHILE.UA=<US X=(UAUS/2)/US MemArbV[UA]=K * (2 * X) * G^3 / (X^2 + G^2)^2 UA=UA+1 WEND. ;==============================
Witch Of Agnesi:This is another "bellshaped curve" like the Gaussian and Lorentz. According to Wikipedia and Wolfram, it was described by Maria Agnesi in a 1748 book that is the oldest surviving mathematical work by a woman. The "witch" in the name comes from a later mistranslation of averisera, the Italian for a "turning sine curve" into avversiera, a female devil, and later simply "witch". The P parameter controls the width of the curve, as a fraction of the full cycle width. This is the width of the peak at halfmaximum height (FWHM). Arb_Agnesi.DAT was created with the default P=0.05:
;==== Witch of Agnesi ==================== P=0.05 A=P * 2 K=K / (2 * A) WHILE.UA=<US X=2 * UA/US  1 MemArbV[UA]=K * 8 * A^3 / (X^2 + 4*A^2) UA=UA+1 WEND. ;==========================================
Catenary Curve:A catenary curve describes the shape of an idealized rope or chain hanging freely between two end points, with no other load than its own weight. The value of A used here is selected such that the ends are at full scale. This was used to create the included Arb_Catenary.DAT file.
;======= Catenary =========== A=0.0765 ;Selected to get full scale in 16K samples WHILE.UA=<US X=0.5 * (UAUS/2)/US MemArbV[UA]=K*A*cosh(X / A) UA=UA+1 WEND. ;==============================
Exponential Growth:The Exponential Growth Arb Arb_Exp_Growth.DAT plots the growth of something whose growth rate is proportional to the current value  the greater it is, the faster the rise. Here we use B as the growth factor and A as the number of time constants to be plotted, where one time constant is the time for the output to increase by the factor B. The time constant is thus 1/A. The default code uses B=2 and A=4, which could represent a plot of 4 doublings (4 time constants) of a bacterial colony:
;===========Exponential Growth =============== A=4 ;Include 4 timeconstants in Arb B=2 ;Growth factor: Output multiplies by B in 1/A time K=K / (B^A) ;Initial value to reach full scale at end WHILE.UA=<US X=UA/US MemArbV[UA]=K * B^(A * X) UA=UA+1 WEND. ;==============================
Exponential Charge And Decay:
Exponential Charge:
The Exponential Charge Arb Arb_Exp_Charge.DAT is the shape of the voltageversustime curve for a capacitor C being charged through a resistor R, where the charging voltage is the fullscale range of the sound card K = 32767. The product of R * C has units of seconds and is known as the time constant, which we'll call T here. This is the time at which the capacitor reaches 63.2% of the maximum voltage. (That's 1  1/e or 0.6321056.) In the code below, we use A to specify how many of these T time constants will be included in the Arb. We don't use T directly there. To use the Arb to model real resistors and capacitors, you need to consider the Tone Frequency used by the Arb. That determines the period of Arb model of the charging curve. Arb_From_Equation sets this as: L.0.ToneFreq=SmplRate / 1024 This spreads the curve over one full waveform screen of 1024 samples, to aid in evaluating the Arb being created. But you are not limited to that when you later use the created Arb for your own applications. The time for one period of the Arb (A time constants) will be 1 / ToneFreq, so the time T for one time constant will be: T = R * C = 1 / (A * ToneFreq). Substituting, we can solve solve for R, C, A, or ToneFreq: R = 1 / (R * A * ToneFreq) C = 1 / (C * A * ToneFreq) A = 1 / (R * C * ToneFreq) ToneFreq = 1 / (R * C * A) ;======= Exponential Charge ============ A=4 ;Include 4 timeconstants in Arb WHILE.UA=<US X=UA/US MemArbV[UA]=K * (1  exp(A * X)) UA=UA+1 WEND. ;==============================
Exponential Decay:
Conversely, the Exponential Decay Arb Arb_Exp_Decay.DAT is the shape of the voltageversustime curve for a capacitor C being discharged through a resistor R, from an initial starting voltage equal to the fullscale range of the sound card. All the same time constant math applies. ;======= Exponential Decay ============= A=4 ;Include 4 timeconstants in Arb WHILE.UA=<US X=UA/US MemArbV[UA]=K * exp(A * X) UA=UA+1 WEND. ;==============================
RC LowPass Square Wave:Arb_RC_LowPass_Square.DAT combines the above Exponential Charge and Exponential Decay to simulate a square wave passed through a simple RC lowpass filter.
Note that this code is for a bipolar square wave that is symmetrical about zero volts, such as the normal Generator Square Wave option. This is slightly more complex than a positiveonly square wave, but in either case we need more than a simple concatenation of Charge and Decay code. To understand the issue, consider simulating a positiveonly square. We start with the Charge code for half the cycle, followed by the Decay code for the remainder. But note that the Charge curve starts at zero volts but doesn't reach the fullscale value; it only approaches it as you increase the number of time constants. Conversely, the Decay curve starts at full scale but doesn't reach zero. The simple code concatenation would thus produce an abrupt step up at the start of the Decay phase, and an abrupt step down to zero at the start of the following Charge. To correct for this, we need to shift each phase by an amount that depends on its end value, which we must precompute so we can include the shift in each sample. For the bipolar square we must also double the range and shift it down so half is negative. Note that here A is the number of time constants in each phase of the square wave. ;======= RC LowPass Square Wave ============= A=4 ;Include 4 timeconstants in each phase D=K * (1  exp(A)) ;Precompute end of Charge phase (where X=1) Q=K  D ;Difference from fullscale K A=A * 2 ;Double A to cover half cycle WHILE.UA=<US/2 X=UA/US V=K * (1  exp(A * X)) MemArbV[UA]=2 * V  D UA=UA+1 WEND. UA=0 D=D + 2 * Q WHILE.UA=<US/2 X=UA/US V=K * exp(A * X) MemArbV[UA+US/2]=2 * V  D UA=UA+1 WEND. ;==============================
Logarithm:Arb_Log.DAT is the plot of a logarithmic curve that has been scaled and offset so that it runs from negative full scale to positive full scale.
The raw equation would look something like Y=ln(X). To facilitate the scaling and offset calculations, we first rewrite it to Y=K * (1 + ln(X)). We then replace X with X=A * UA/US + B, where US is the total number of sample points in the Arb, and UA is the sample index which runs from 0 to US1. The sound card fullscale value is K=32767, and we want the 0th point to be K or 32767. When UA = 0, X=A * UA/US + B becomes X=B, so we can insert that into Y=K * (1 + ln(X)) to get Y=K * (1 + ln(B)). Since we want the result to be K here, we can set Y=K and get K=K * (1 + ln(B)). Dividing both sides by K gives 1=1 + ln(B), thus ln(B)=2, hence B=exp(2). To find the value for A we use the condition when UA=(US1) and set that to give an output of +K. K=K * (1 + ln(X)) then becomes 1=1 + ln(X) and ln(X)=0. Since X=A * UA/US + B, we get ln(A * UA/US + B) = 0. But we know that 0 is the log of 1, so we can remove the logarithm to get A * UA/US + B = 1 and solve for A when UA=US1 to get A=(1  B) * US / (US1). We solve for B and A outside the main loop, since these don't change during the Arb calculation. ;======= Log ============= B=exp(2) ;Constant to set 0th point to K A=(1  B) * US / (US1) ;Constant to set final point to +K WHILE.UA=<US X=A * UA/US + B ;Scaling and offset to get +/FS range MemArbV[UA]=K * (1 + ln(X)) UA=UA+1 WEND. ;=========================
Power Law:This code creates the curve of Y=X^P as X runs from 0 to 1, scaled so that the output runs from 0 to K, the sound card fullscale value. The code below shows P=2 to give a square law, but any positive value will work, including fractions. Using P=0.5 will give the same curve as Arb_SquareRoot.DAT in the next subtopic. Included waveforms are Arb_Power_2.DAT, Arb_Power_3.DAT, Arb_Power_5.DAT, and Arb_Power_10.DAT for powers 2, 3, 5, and 10. The image below shows all of these superimposed for comparison:
;===== Power Law ====================== P=2 ;Power, may be decimal P=abs(P) ;Not negative WHILE.UA=<US ;Compute 0 to US points X=UA / (US  1) ;Scaling to get FS at peak MemArb0[UA]=K * X^P ;Compute and save UA=UA+1 ;Next sample WEND. ;========================================
Square Root:Arb_SquareRoot.DAT is the plot of Y=sqrt(X) as X runs from 0 to 1, scaled so that the output runs from 0 to K, the sound card fullscale value.
;======= Square Root ============= WHILE.UA=<US X=UA/US MemArbV[UA]=K * sqrt(X) UA=UA+1 WEND. ;==============================
Ellipses And Circles:
Half Ellipse (Half Circle):
Arb_Half_Ellipse.DAT is the plot of the top half of an ellipse or a circle; the appearance depends on the Yaxis magnification and the tone frequency the Arb is run at. At fullscale magnification with one Arb cycle (one half of the ellipse) on the screen, as shown when you run this code in Arb_From_Equation, you see a halfellipse that looks like a slightly squashed circle. If you double the tone frequency you see two halfcircles (assuming your monitor has square pixels). ;======= Half Ellipse (Half Circle) ============= WHILE.UA=<US X=2 *(UAUS/2)/US MemArbV[UA]=K * sqrt(1  X^2) UA=UA+1 WEND. ;=============================
Alternating Half Ellipse And Dual CirclesArb_Alt_Half_Ellipse.DAT alternates the top (positive) half of an ellipse or circle with the bottom (negative) half in each full cycle of the Arb. It looks somewhat like a deformed sine wave. However, when the same wave is output on both Left and Right channels, but with one channel inverted, you see two adjacent full circles. The Circles.GEN generator setup has been created to do exactly this.
If you cut the screen magnification in half (PgDn key) you will see two ellipses. If you then double the Left and Right tone frequencies from 46.875 to 93.75 Hz you will see 4 circles. ;======= Alternating Half Ellipse ("Circle" Wave)=== WHILE.UA=<US/2 X=4 * (UAUS/4)/US MemArbV[UA]=K * sqrt(1  X^2) MemArbV[UA+US/2]=K * sqrt(1  X^2) UA=UA+1 WEND. ;==============================
Sinc Function sin(x)/x:The sinc function looks like a sinusoid that decays on either side of a central peak, somewhat like a "ringing" bellshaped curve:
In the code supplied here, parameter F controls the "frequency" of the sinusoid; it is essentially the number of halfcycles (positive or negative peaks) in each half of the waveform, counting the central peak. Note that if F is an integer, the waveform will start at 0 and end at 0. However, since the waveform is mirrored about the center, that also means that when the waveform repeats it is likewise mirrored about its ends. For example, if the start is at 0 with a positive slope, the end will have a negative slope down to 0 that will not "splice" smoothly with the next start rising up from 0. To get a smooth splicefree wave, you must set F to halfway between two integers. The image above (which is also the Arb_Sinc85.DAT waveform) used the default F=8.5. Note that it starts and ends at a positive peak, instead of a zero, so it will splice perfectly. ;=== Sinc Function =============================== F=8.5 ;"Frequency" WHILE.UA=<US/2 X=F*2*pi*UA/US Y=K*sin(X) / X MemArbV[UA+US/2]=Y ;Fill from center up MemArbV[US/2UA]=Y ;Fill from center down UA=UA+1 WEND. MemArbV[US/2]=K ;Center = 1.00 ;============================================
Cosine Window Functions:Here we include code to create Arbs of several common window functions, the same ones used by Daqarta to reduce spectral leakage. They all use the same code, but with different parameter values. (Note that in the plot below all three Blackman curves nearly overlay, so at this scale they appear as a single yellow line.)
Hann (Haversine):Arb_Hann.DAT was created with the code below: ;=============================================== A=0.5 ;Hann (same as Haversine) B=0.5 C=0 ;General Cosine Window: WHILE.UA=<US X=2 * pi * (UA / (US1)) ;Center the window in Width Y=A  B * cos(X) + C * cos(2 * X) Y=Y * K MemArbV[UA]=Y UA=UA+1 WEND. ;===============================================
Hamming:Arb_Hamming.DAT was created using the following parameters in the above Cosine Window code: A=0.54 ;Hamming B=0.46 C=0
Blackman:Arb_Blackman.DAT was created using the following parameters in the above Cosine Window code: A=0.42 ;Blackman B=0.5 C=0.08
Blackman Exact:Arb_BkmExact.DAT was created using the following parameters in the above Cosine Window code: A=0.42659071 ;Blackman Exact B=0.49656062 C=0.07684867
BlackmanHarris:Arb_BkmHarris.DAT was created using the following parameters in the above Cosine Window code: A=0.42323 ;BlackmanHarris B=0.49755 C=0.07922
FlatTop:Arb_FlatTop.DAT was created using the following parameters in the above Cosine Window code: A=0.2810639 ;FlatTop B=0.5208972 C=0.1980399
Arb_From_Equation Macro Listing:;<Help=H491F UK=16 ;16K = 16384 samples (1,2,4,8,16 allowed) W=100 ;Waveform uses 100% Width of above W=abs(W) ;Must be positive IF.W=>100 ;Can't use more than 100% W=100 ENDIF. Spect=0 ;Spectrum off Sgram=0 ;Spectrogram off Xpand=0 ;Show full horzontal range TraceMag=0 ;Show full vertical range Msg="Creating Arb in Memory..." A.LoadGEN="ArbTest" ;GEN to hold MemArb, muted Full Scale range Ch=0 ;Use MemArb0 MemArbV#X=0 ;Remove existing MemArb or Arb, if any MemArbV#N=UK ;Create 1, 2, 4, 8, or 16K MemArb L.0.Arb0=1 ;Set output active UN=MemArbV?N ;Get size in samples K=32767 ;Sound card +/ fullscale value Decimate=0 ;Decimate OFF L.0.ToneFreq=SmplRate / 1024 ;One cycle on screen US=W/100 * UN ;Samples in active Width section UA=0 ;MemArb sample index ;==== Sine Wave === (REPLACE as desired) ==================== WHILE.UA=<US MemArbV[UA]=K*sin(2*pi*UA/US) ;Sine wave, scaled to fit in Width UA=UA+1 WEND. ;============================================================ WaitSecs=3 ;Wait for sound card output buffer fill Msg= MemArbV="<Save:" See also Memory Arbs (MemArb07), Arb Files as Controllers, MemArb_To_File Macro, Wave Dialog, Arb Wave. 

GO:
Questions? Comments? Contact us!We respond to ALL inquiries, typically within 24 hrs.INTERSTELLAR RESEARCH: Over 35 Years of Innovative Instrumentation © Copyright 2007  2023 by Interstellar Research All rights reserved 