Data AcQuisition And Real-Time AnalysisScope - Spectrum - Spectrogram - Signal Generator
Software for Windows
Science with your Sound Card!
Contact us about
Sound Card Missing Fundamental Mini-App
The Missing_Fundamental macro mini-app is included with Daqarta. It demonstrates the extent to which the brain perceives the fundamental frequency of a harmonic series of tones, even if that fundamental is not present.
For example, a tone complex consisting of only 220, 330, and 440 Hz sine-wave components may nevertheless be heard as 110 Hz. This is the greatest common divisor of the component frequencies, making it the most likely candidate for the missing fundamental, with the component tones thus representing the 2nd, 3rd, and 4th harmonics.
Determining whether you are hearing the fundamental or just the harmonics can be tricky. Researchers do this by presenting sequential pairs of tone complexes with different harmonic structures. Pairing the tones like this allows quick A-B comparisons: Does the second tone sound higher or lower than the first?
In the Missing_Fundamental mini-app, the first (A) tone complex is on for 300 ms, immediately followed by 300 ms of the B tone, then 400 ms of silence for a 1-second overall cycle which repeats indefinitely.
The default parameters result in the following A and B tones, where N gives the harmonic number; notice that both A and B have the same top frequency of 550 Hz, but for A it is the 5th harmonic of the (missing) fundamental of 110 Hz, while for B it is the 6th harmonic of 91.667 Hz (also missing, as is the 2nd harmonic at 183.333 Hz):
The spectrogram shows this graphically, with the missing components added as dotted lines:
You should note that besides the identical top frequencies, all of the other components that are actually present in the B tone are higher than those in the A tone. Yet for most people the B tone sounds definitely lower in pitch, because of the lower fundamental frequency that is implied by the harmonics.
Different parameters can yield different results. Just raising everything by 4 octaves (by setting the Fundamental control from 110 to 1760 Hz) can cause the apparent high-low sequence to reverse to low-high.
It turns out that there are innate differences between individuals regarding how readily they perceive the missing fundamental, as opposed to the lowest tone actually present (or any sort of average). Certain parameter combinations can highlight these differences. The Missing Fundamental mini-app allows you to change the effective fundamental frequency, the lowest harmonic to be included, the total number of harmonics, and the harmonic spacing.
This two-tone protocol is an extension of that used by researchers who showed that these individual differences in missing fundamental perception reflect measurable brain differences. (See the Schneider, Sluming, et. al. entry in the External References and Links section, below, for the full citation and a link to the PDF of this paper.)
The researchers studied the relative left- and right-hemisphere sizes of a brain structure called the lateral Heschl's gyrus (lHG) that is known to be involved in pitch detection. The left lHG was larger and showed stronger electrical responses than the right lHG in subjects who tended to hear the missing fundamental, whereas the opposite was true for those who tended to hear just the tones that were actually present.
Interestingly, their tests included many musicians, but there was no correlation of these differences with musical ability. The musicians had larger lHGs overall, but missing fundamental detection correlated only with the left-right assymetry, not absolute size... just the same as for non-musicians with their smaller lHGs.
The Missing Fundamental mini-app allows you to duplicate any tone pair from the above experiments exactly, including level calibration.
It does not, however, attempt to present specific sequences of tone pairs; it either presents the same tone pair repeatedly until you change the settings, or else it optionally steps through a range of fundamental frequencies with all other settings held constant.
You are not limited to the tones of the original study; your explorations can cover a wider frequency range, or use entirely different harmonic numbers. In particular, you can explore the effects of relative harmonic phase, and hence periodicity, on the perception of the missing fundamental. See the Phase Experiments subtopic for more information.
Missing_Fundamental uses a Custom Controls dialog that allows adjustment of various parameters. You can open this Help topic by right-clicking anywhere in the dialog:
The Fundamental, Hz control defaults to 110 Hz. This is the value used as the fundamental for the harmonic series, even when that fundamental itself is not present, as in the default Fundamental OFF button state. The default Two-Tone Mode uses the Fundamental value directly in creating the first (A) tone of the two-tone pair. The second (B) tone is derived from A based upon other control settings, as described below under the 1-Harmonic A-B Increment button.
Lowest Harmonic Number defaults to 2. This means that the A harmonic series begins with the 2nd harmonic, which is twice the Fundamental value.
Total Harmonics defaults to 4. This total includes only the harmonics of one tone (A or B), and does not include the fundamental (if present). In the default case with Lowest Harmonic Number at 2, Fundamental at 110 Hz, and Fundamental OFF, the A tone will consist of harmonics 2 through 5, at 220, 330, 440, and 550 Hz.
The Missing_Fundamental mini-app uses one stream of the Daqarta Generator per tone component, whether A or B, harmonic or fundamental. The Generator has 8 streams, so the Total Harmonics default of 4 is the maximum you can set in Two-Tone mode. If you try to exceed that it will be forced back to 4, with a message: "4 Harmonics MAX in Two-Tone mode."
1-Harmonic A-B Increment indicates that the lowest harmonic of the B tone will be 1 harmonic number higher than the A tone. (You can set this increment from 1-4 via repeated clicks on the button. After 4, the next click will return to 1. You can move in the reverse direction by holding down the SHIFT key while you click the button. This multi-click operation is used with several of the other buttons, discussed below.)
The B tone will use the same Total Harmonics as A, so instead of running 2 through 5 the default B harmonics will run from 3 through 6. However, the frequency of the top B harmonic is always set to match that of the top A harmonic, or 550 Hz in this case. So if 550 Hz is the 6th B harmonic, then the (missing) fundamental must be 550 / 6 = 91.667 Hz, the 3rd will be 275, the 4th will be 366.667, the 5th will be 458.333, and of course the 6th will be 550.
The Show Values button allows you to display these on a resizeable custom meter. Note that crest factor (CF) values are only shown in Waveform Display mode:
The Fundamental OFF button can be clicked to Fundamental ON, but only if Total Harmonics is 3 or less in Two-Tone mode, due to the above-mentioned 8-voice limit. Otherwise the click will skip to Fundamental ONLY. The ON and ONLY conditions are just for quick reference, not normally part of a test.
An additional click past ONLY takes you to Fundamental OFF, STEP, which will step all frequencies up by 2 semitones (1/6 octave) after each two-tone pair. After 12 steps (24 semitones or two octaves), the cycle repeats. This allows you to quickly tell if there are perceptual flips from high-low to low-high, or vice-versa. The Show Values display is updated at each step, so you can note the frequency range of any changes.
The Calibrate Level button is discussed under the Initial Set-Up and Calibration subtopic, below.
The default Waveform Display mode triggers only on the B wave, so you will see a rolling waveform while the A tone is sounding, then a stable B waveform. You can hit Pause (or use ALT+P) to freeze the waveform while either A or B is visible, such as to save it to a file or a memory array, but only B will trigger at a repeatable point.
Here's a comparison of B waveforms with Fundamental OFF and Fundamental ON, using the default settings except with Total Harmonics reduced to 3. It was created by hitting Pause when each B waveform was visible, then saving each to the Juxt Trace Memory Array and adjusting the Spacing and Offset with the Array display on. The main Daqarta window was then copied to the Windows clipboard with ALT+PrintScreen, and pasted into Windows Paint for cropping and adding colored text labels:
Notice that the waveform is very similar between Fundamental OFF and Fundamental ON. In particular, note that both waveforms have the same period between the highest peaks: 11.364 ms, corresponding to the 88 Hz frequency of the B fundamental, even though that fundamental isn't really present in the OFF case. This observation features prominently in some proposed explanations of how the auditory system is able to perceive the missing fundamental. See the Auditory Theories subtopic, below.
The Zero Phase button indicates that all harmonics are aligned in time with their fundamental. This produces the large waveform peaks shown above. Repeated clicks of this button advance it through +/- Phase Factor (which enables the Phase Factor control), then Minimum-Peak Phases, and finally Random Phases (which enables the Randomize Phase button below it). All of these are discussed under the separate Phase Experiments subtopic.
If you click Waveform Display it will advance to Spectrum Display. The spectrum will be shown with X-log and Y-log axes, with Decimate active using a Decimate Factor automatically selected (along with X-Axis eXpand) to give best resolution of the spectral peaks. This image was created as for the waveform display above, but with no Spacing or Offset of the traces:
A second click will advance to Spectrogram Display, again with optimized Decimate Factor and eXpand settings. Since spectrograms can't be superimposed to show the differences between Fundamental OFF and ON, this image just shows the OFF condition for both A and B tone complexes of the original default 4-harmonic tones:
Spectrum Window is active in Spectrum Display and Spectrogram Display by default. This is usually the best option because it reduces the "skirts" around the spectral peaks. However, it does make the tips slightly wider. You can use ALT+W to toggle the Window off for sharper peaks, especially in Spectrogram mode, at the expense of trash due to the increased skirt amplitudes.
The default Two-Tone Mode allows up to 4 harmonics with a missing fundamental, or 3 plus the fundamental, on each tone complex. Alternatively, you can click the Two-Tone Mode button to Continuous Tone (described in detail under its own subtopic) that allows up to 7 Total Harmonics (plus the fundamental, with Fundamental ON) in a single ongoing tone complex.
Holding down the ALT key while clicking the Two-Tone / Continuous button takes you to Play Music mode. This disables all other controls in the mini-app and starts a DaqMusiq MIDI rendition of "Frere Jacques" called MissFundamental.DQM. The song (melody only) is played with 8 sine-wave voices, one per harmonic, including the fundamental through the 8th. This allows you to toggle the fundamental and/or any of the harmonics off and on during the performance. See the separate Play Music Operation subtopic.
Once you start the Missing_Fundamental mini-app, the very first thing you should do is adjust the volume. (The F9 key opens Daqarta's volume slider dialog.) Whether you are listening with headphones or speakers, it is important to avoid overdriving your system. Without changing any settings in Missing_Fundamental, adjust the volume for a comfortable listening level. Then see if the tone quality (timbre) changes suddenly as you reduce the volume. If so, your system was distorting on the higher level, so keep it below that.
The study by Schneider, Sluming, et.al. used sound levels that were 50 dB above the listener's detection threshold. (See the External References and Links section, below, for the full citation and a link to the PDF of this paper.)
If you want to duplicate that, click the Calibrate Level button. The digital level of the generated signal (before the output DAC) will be reduced by 50 dB, to 10^(-50 / 20) = 0.00316 = 0.316% of the normal level.
The Daqarta volume control dialog will open and a message will appear:
"Adjust volume until you can just detect the tones, then toggle Calibrate off for 50 dB SL Two-Tone test."
The volume control acts on the analog output stream after the DAC, so when you set the analog volume such that you can just detect the signal, then restore the pre-DAC digital level, the overall sound level will be 50 dB higher than your detection threshold.
Note that the digital level of 0.316% means that the signal is using less than 7 bits of the 16-bit DAC range. There will be more distortion during this step... roughly 100 times more, in fact, or about 1% overall. But since you are adjusting the volume such that you can barely hear the signal, that 1% distortion will be about 40 dB below your detection threshold so you will not be able to hear it.
Note also that your hearing is naturally more sensitive in some ranges than others, with the most sensitive region being around 1000 Hz and falling off above or below that. So if you calibrate at 110 Hz and test at (say) 880 Hz, the sound will be louder (ie. more than 50 dB above your 880 Hz threshold).
It's not clear how Schneider, Sluming, et. al. calibrated to get their 50 dB levels, but the important thing for your own research is to keep track of whatever approach you use so that you can repeat it as needed.
As noted in the Introduction, with the default parameters most people hear the A-to-B transition as high-to-low, even though the B component frequencies are actually higher than those in A (except for the identical top frequencies).
But you may hear the transition as the opposite direction. Regardless of which way you hear it, the direction may change at higher or lower Fundamental settings. Try moving it in octave steps: 27.5, 55, 110, 220, 440, 880, 1760 Hz.
Once you find a frequency with the opposite direction, try searching back to find exactly where the change takes place. You will probably find there is a large range where your impression of the direction is ambiguous; sometimes it's one way, sometimes the other.
Often the perceived direction depends on the path you take to get there. For example, the author usually perceives the default 110 Hz setup as definitely high-low. Raising it to 220 Hz gives a definite low-high direction, at least when listening through headphones at moderate levels. But going back to 110 and working up in 10 Hz steps yields high-low the whole way, to 220 Hz and beyond. This phenomenon may be like viewing reversing in-out Necker cubes, or a photo of lunar craters, where the preferred direction can change; once you get conditioned to a certain direction it tends to persist.
Sometimes a very slight change in listening conditions can prompt a direction change. When listening to the above 220 Hz setup with headphones and hearing a definite low-high direction, even a slight reduction in volume caused it to revert back to high-low... often as small as 1-2 dB, after a preliminary hunt established the threshold region (about 6 dB louder than the 50 dB level obtained by Calibrate Level).
Near the level threshold there seems to be a strong psychological component to the direction change. When above the threshold level and stepping downward, for example, sometimes the direction changed as expected even when the level did not. (To do this type of test yourself, have an assistant change, or not change, the volume while you listen without being able to see what's actually happening.)
What causes this level-dependent effect? Consider that with a 220 Hz fundamental the upper components are near or above 1000 Hz, where they are not well-separated by the auditory system. If the missing fundamental can't be clearly determined, the system might be expected to respond to just the average component frequencies. This would give a low-high direction.
Notice that the louder condition gives low-high and the softer gives high-low. This implies that even when the components are louder, and presumably clearer due to being farther above any background noise, they are nonetheless not separated.
Intermodulation distortion (IMD) can cause difference or combination tones that are not present in the original signal. Note that this distortion can take place in the sound card amplifier, the headphones, or even your ears. Since the component tones are at harmonic numbers that differ by 1 (such as the 4th and 5th for the A tone), the difference tone will be exactly at the fundamental frequency.
Most forms of distortion produce stronger distortion products at higher levels, but that would tend to make the missing fundamental more detectable, leading to a high-low direction instead of the actual low-high.
However, crossover distortion can create IMD in amplifiers (but not headphones or ears). By its nature crossover distortion is actually worse at lower levels. (See Sound Card Distortion - Theory And Measurement for details.) That might explain why the missing fundamental is more detectable at lower levels. How can you tell?
Daqarta's IMD Meter mini-app can measure intermodulation distortion. A loopback cable from the headphone output back to the line input would allow measurement of the IMD in the headphone amplifier. If it rises sharply as the volume is lowered into the region of the high-low direction, you might count that as evidence for crossover being the culprit.
But there is a much simpler test: At the higher level where the low-high direction is heard, just move the headphones away from your ears. (This may be easier with on- or over-the-ear instead of in-the-ear phones.) This reduces the volume of the sound to your ears without changing the amplifer level, so there is no distortion change. If the direction switches to high-low, it proves that amplifier distortion is not to blame. That's exactly what happened in the author's tests.
The remaining possibility is that the phenomenon is due to something in the auditory system itself. One likely suspect is the fact that the tuning sharpness of auditory filters is worse at high levels, so reducing the level could increase the ability of the system to discriminate the individual components and thus determine the missing fundamental.
But curiously, the low-high direction at 220 Hz switches back to high-low by about 300 Hz... and raising the level doesn't bring back low-high. By around 1000 Hz the low-high response has returned at high levels, with high-low at low levels. Above 1200 Hz it is always low-high regardless of level.
More research is clearly needed!
As noted in the Overview section, the Harmonic A-B Increment controls the lowest B harmonic number relative to the Lowest Harmonic Number setting, which applies to A. The harmonic numbers increase in steps of one above that, until the Total Harmonics value is reached. The increment can be set from 1-4, which with the other settings at their defaults gives these harmonic numbers and frequencies:
Harmonic A-B Increment --- 1 ---- --- 2 ---- --- 3 ---- --- 4 ---- A5 550 B6 550 B7 550 B8 550 B9 550 A4 440 B5 458.33 B6 471.43 B7 481.25 B8 488.89 A3 330 B4 366.67 B5 392.86 B6 423.50 B7 427.78 A2 220 B3 275 B4 314.29 B5 343.75 B6 366.67 A1 (110) - - - - B1 (91.67) - - - B1 (78.57) - - B1 (68.75) - B1 (61.11)
Notice that as the Increment increases, all of the component frequencies increase as well (except the constant top frequency), but the missing fundamental decreases.
The Lowest Harmonic Number, as noted above, applies to the A tone. It can be set from 2 to 16. If you set it to 4, with Total Harmonics reduced to 2, the Harmonic A-B Increment at 2, and the Fundamental at 332.2 Hz you will get the following:
A5 1661 B7 1661 A4 1328.8 B6 1423.7 ... ... A1 (332.2) B1 (237.3)
This is a close approximation of the two-tone test found on the Steve Mould - Science Presenter site under "Audio Illusion: Do you hear the missing fundamental?" (See the External References and Links section, below.) The actual tone frequencies were not published on the site; these were obtained by analyzing the spectrum with Daqarta.
As-is, this seems to give a good split between those who hear it as high-low and those who hear low-high.
This general setup also makes a good test for overall sensitivity to frequency range. Try setting Fundamental back to the 110 Hz default, then toggling Show Values on. Now click the Fundamental OFF button 3 times, past ON and ONLY to Fundamental OFF, STEP.
Now the top frequency will step from 550 Hz (5 times 110) to 2200 Hz (2 octaves higher, or 20 times 110) in 12 steps. For the author, the direction starts out as definitely high-low, but when the top passes 1100 Hz (A missing fundamental of 220 Hz and B of 157 Hz) the perception changes to low-high.
Advancing the Harmonic A-B Increment from 2 to 3 and then to 4 makes the initial high-low effect even more pronounced.
Even more surprising, with Fundamental set to (say) 80 Hz the first few steps are low-high. But when the A fundamental crosses 110 Hz (top over 550 Hz) the direction switches to high-low, then when it passes about 220 Hz (top over 1100 Hz) it changes back to low-high, as above. For the author, this behavior seems to be essentially the same with any Harmonic A-B Increment settings.
Some of the parameters for Two-Tone Mode are preset in the macro script, instead of having adjustable controls. These parameters set the timing of the two-tone cycle, as well the order of A and B presentation, the application of phase changes, the harmonic spacing, waveform type, and the number of frequency steps and range of the Fundamental OFF, STEP mode.
All of these are set at the start of the Missing_Fundamental macro script; you can easily change them by single-clicking on Missing_Fundamental in the Macro List, then clicking the Edit button to view the script, and editing the Definition directly. Here is the start of the script:
;<Help=H4913 R=15m ;Rise/Fall times for A/B two-tone test H=300m ;On (High) time per tone G=0 ;Gap between A and B tones (none) C=1000m ;Cycle time for 2 tones plus silence QX=0 ;QX=1 to eXchange A,B order to B,A QP=2 ;Phase change only on B (1=A, 3=both) U1=1 ;A harmonic increment U2=1 ;B harmonic increment UW=0 ;0=Sine, 1=Tri, 2=Ramp, 3=Sqr, 4=Pulse W=4 ;Sweep limit freq = W times fundamental QN=12 ;Frequency steps in above sweep range
The cycle-timing parameters R, H, G and C are in seconds, so R=15m (note the 'm') means that the Rise (and Fall) times are 15 msec each. These 4 parameters specify a different default cycle timing from the one used by Schneider, Sluming, et.al. (See the External References and Links section, below, for the full citation and a link to the PDF of this paper.)
The timing they used would be:
;<Help=H4913 R=10m ;Rise/Fall times for A/B two-tone test H=500m ;On (High) time per tone G=250m ;Gap between A and B tones C=1500m ;Cycle time for 2 tones plus silence
However, they repeated the tone pair only once (A, B, A, B) then waited 2 seconds during which the subject indicated whether the pitch seemed to move from low to high or high to low. The tone parameters were then changed for the next test.
The Lowest Harmonic Number in their tests was either 2, 3, 4, or 7. When they used 2 or 3, the equivalent Harmonic A-B Increment was 1. When they used 4 or 7 it was 2. Thus, their lowest A-to-B harmonic number transitions were always one of:
2 -> 3 3 -> 4 4 -> 6 7 -> 9
The Missing_Fundamental mini-app allows you to set the Lowest Harmonic Number from 2 to 16, and the Harmonic A-B Increment from 1 to 4.
Within the tones of either A or B, the harmonics in Schneider, Sluming, et.al. always incremented in steps of 1, as set here via the default U1=1 for A and U2=1 for B. You can experiment with larger steps for one or both.
You can change QX=0 to QX=1 to reverse the A,B order to B,A.
Schneider, Sluming, et.al. did not investigate phase as a parameter. This mini-app allows you to apply phase changes as selected by advancing the Zero Phases button and using the Phase Factor control or Randomize Phase button. You can apply these changes to either or both A and B tone complexes as set via parameter QP. The default here is QP=2 to only apply phase changes to B; you can use QP=1 to apply them only to A or QP=3 to apply them to both. See the separate Phase Experiments subtopic below for more information.
The UW=0 control sets the default waveform for each harmonic to Sine. The possible options you may wish to experiment with are:
Note that the Ramp and Pulse waveforms normally allow you to change settings such as ramp slope or pulse widths for each stream (each harmonic, in this case). Here they are fixed such that in Ramp mode each component rises slowly and drops abruptly, and in Pulse mode the pulse is positive for 1/8 of a cycle, then negative for 1/8, then zero for the remainder.
W=4 and QN=12 control the frequency steps in Fundamental OFF, STEP mode. W sets the upper limit of the fundamental, as a factor to be multiplied by the current Fundamental frequency. So in the default case with Fundamental set to 110 Hz and W=4, the maximum fundamental (on the last step) will be 440 Hz, or a 2 octave increase.
QN=12 sets the number of steps above the initial Fundamental setting. The steps are exponential, so in the default case where W=4 (2 octaves) each step will be 1/6 octave or 2 semitones.
These parameters are also used in Continuous Tone mode for Fundamental OFF, SWEEP operation, but they behave somewhat differently since that uses a continuous frequency sweep instead of discrete steps. The total sweep duration is QN * C seconds, which in the default case will be 12 * 1000 msec = 12 seconds. W still sets the maximum frequency as above, so the sweep would run from 110 Hz to 440 Hz in 12 seconds. The sweep moves at an exponential rate such that the time for the first octave (110 to 220 Hz) would take 6 seconds, the same as the second (220 to 440 Hz).
Clicking the default Two-Tone Mode button toggles to Continuous Tone. This mode allows up to 7 Total Harmonics, even with Fundamental ON.
The 1-4 Harmonic A-B Increment button changes to 1-4 Harmonic Increments, and now controls the spacing between harmonics in the single continous tone. When set to 1, with Lowest Harmonic Number set to 2, the harmonic series will be (1), 2, 3, 4, etc. With Harmonic Increments set to 2 it would be (1), 2, 6, 8, etc.
The Calibrate Level button changes to Levels EQUAL, and can be toggled to Levels 1/N. The latter means that the amplitude of each component is proportional to the reciprocal of its harmonic number. Besides whatever effects this might have on the missing fundamental phenomenon, it also allows nice demonstrations of waveform synthesis from sine wave components. With Fundamental ON, Lowest Harmonic Number set to 2, and Harmonic Increments set to 1, the tone will consist of all harmonics up to the limit set by Total Harmonics, falling off at 1/N. This will approximate a ramp waveform. Increasing Total Harmonics will sharpen it.
Toggling back to Fundamental OFF and increasing Harmonic Increments to 2 will also give a ramp wave, but at twice the frequency. Increasing Lowest Harmonic Number to 3 and Harmonic Increments to 3 will give a ramp at 3 times the frequency, while setting these both to 4 will give 4 times the frequency. Toggle Show Values on to see what's going on.
Likewise, with Fundamental ON, Lowest Harmonic Number set to 3, and Harmonic Increments set to 2, the tone will consist of only odd harmonics falling off at 1/N, which will approximate a square wave.
With Fundamental OFF, Lowest at 2, and Increments at 4, you get a square wave at twice the frequency.
Clicking Fundamental OFF advances it to Fundamental ON and then to Fundamental ONLY, just as for Two-Tone Mode, but the next click is Fundamental OFF, SWEEP (instead of STEP).
As noted in Two-Tone Macro Parameters, the SWEEP mode for Continuous Tone performs a continuous exponential frequency sweep from the Fundamental frequency to 4 times that frequency (two octaves), over an interval of 12 seconds. You can change the time and frequency range factor via the same macro parameters that control STEP operation in Two-Tone Mode. You can monitor the current frequency values via Show Values, and you can see them graphically by clicking the Waveform Display button to Spectrum Display or Spectrogram Display.
With Continuous Tone mode it is more difficult to be sure you are actually hearing a missing fundamental, since there are no separate A and B tones to compare.
Set Total Harmonics to 7. Listen carefully as you move back and forth between OFF, ON, and ONLY conditions, and notice that the tonal quality doesn't change much from OFF to ON; both cases are much more strident than the pure sine wave of the ONLY condition.
At this point you may be thinking that since the OFF condition (harmonics without fundamental) sounds so little like the ONLY condition (just the fundamental), how can it be claimed that it is somehow inducing a perception of the "missing" fundamental? Wouldn't it be more correct to simply say that when the harmonics are present, they dominate the perception?
To get a better sense of the origin of the claim, try going to the ONLY state and reducing the Fundamental frequency from 110 Hz down to 55 (musical A1). Your speaker system or headphones will need good bass response for you to hear this well. You should notice a periodic pulsing or fluttering quality to the sound, possibly felt as much as heard, as if you were hearing and feeling the individual waveform peaks passing like blades on a fan.
Now when you add the harmonics (Fundamental OFF or ON), you will hear this same "periodicity" effect in either case, at the same rate you hear in the ONLY condition.
Caution: The harmonics-present conditions will sound much louder, even though they have less than half the RMS level of the fundamental alone. (Toggle the Voltmeter on with the ALT+V keys to see this.) This is because our ears are not as sensitive at low frequencies, but hear the higher harmonics much better.
The astute observer will notice that the same periodicity is visible in the Fundamental OFF and ON waveform displays... in fact they look almost identical (displaced vertically here for clarity):
This leads to the natural assumption that the ear is somehow analyzing the waveform and detecting the periodicity. But things are not completely straightforward, as discussed in the Auditory Theories subtopic.
You may have heard about the missing fundamental effect being used musically to play notes that are lower than ordinary instruments can create... or even lower than humans can actually hear. The Play Music mode allows you to experiment with this.
Holding down the ALT key while clicking the button marked Two-Tone Mode or Continuous Tone takes you to Play Music, which will cause all other Missing_Fundamental controls to be disabled until you click on the button again (with or without ALT).
In Play Music the display is set to Pitch Track (in the Sgram/PT control dialog), and Pitch-to-MIDI is activated after loading a DaqMusiq MIDI setup called MissFundamental.DQM. This setup plays a rendition of "Frere Jacques" with 8 sine-wave voices, one each for the fundamental plus harmonics 2 through 8. These voices play the melody only, without the original chords used in the Frere Jacques setup.
The Instrument for each voice is set to Ocarina, which creates a clean sine wave tone when played by the standard Microsoft GS Wavetable synthesizer. This is important so that each voice will be a simple harmonic of the fundamental.
Clicking the Instrument On/Off (Ocarina) button of a voice allows you to toggle the fundamental (voice 1) or any harmonic 2-8 off and back on again at will while the song plays. (Caution: The voices all stay in sync as long as at least one is active; if you toggle all 8 off you may have trouble getting them back in sync. If so, just toggle the Pitch-to-MIDI On/Off button off and back on.)
You may find that this is all rather anti-climactic, since the song just sounds a bit thinner or less robust without the fundamental. The effect may be a lot more compelling when used to create really low notes with an orchestra or a pipe organ. That's because, besides our ears, we sense low notes with our whole body. Since the waveform created will have the periodicity of the missing fundamental, there will be peaks and dips in air pressure (as well as seat and floor vibrations) at the fundamental frequency, which we can feel directly.
If you want to explore this, you can shift the entire song to a lower range. To do that, open the Voice 1 Setup dialog by clicking on that button. Then delete the leading semicolon from the first line of the script, so that it reads n9=-12. That will shift everything down by one octave (12 semitones).
The first note of the fundamental will change from B2 at 123.471 Hz to B1 at 61.735 Hz. This will be hard to hear among the other harmonics playing, both because our ears are less sensitive at lower frequencies, and also because speakers (and headphones) are less sensitive as well. So you might very well not detect a difference when you toggle the fundamental off. But that doesn't really prove you are hearing the missing fundamental, it might just indicate that you can't hear the fundamental in any case.
To prove you are hearing a missing fundamental you can toggle Voice 1 off, along with all voices except Voice 2. Now start toggling the higher-numbered voices on; if you hear lower pitches than with Voice 2 alone, it must be due to the missing fundamental effect. This works even with inexpensive headphones; it's typically a rumbling, growling sound compared to the clean 2nd harmonic with Voice 2 alone.
If you change the first line to n9=-24 everything goes down by 2 octaves, so the first note will be B0 at 30.868 Hz. Using n9=-36 will take it down by 3 octaves to B-1 at 15.434 Hz.
The mystery of the missing fundamental is that we are hearing something that is "not really there"... or is it? Consider a tone complex consisting of a fundamental at 88 Hz, plus harmonics 3 through 5 (at 264, 352, and 440 Hz, respectively). Compare it to the same case without the fundamental, only the harmonics:
There is a definite periodicity in both waveforms at the 88 Hz fundamental period (11.364 msec), even when that component isn't there, as shown by the Spectrum Display view of the same tones:
So it seems obvious that the auditory system must be detecting this waveform periodicity, and we expect that this should be simple to do... after all, we can see the periodicity with our eyes!
But nothing about the auditory system is simple. The main issue it has to solve is that neurons, which ultimately must convey to the brain anything we can hear, are much too slow to handle the full frequency range of normal sounds. The ear solves this with a divide-and-conquer approach using many neurons in parallel, each handling only a tiny sliver of the total frequency range.
Sound enters the fluid-filled spiral cochlea (from the Greek for "snail") as a pressure wave that excites the basilar membrane, which due to its tapering width (and mass and stiffness) vibrates at different locations for different sound frequencies. The pattern of vibration looks roughly like the spectrum seen above.
All along the length of the basilar membrane are sensory inner hair cells (IHCs) that detect the vibration at each location. Motion causes an IHC to excite fibers running to neurons in the cochlear nucleus. When a neuron fires, it creates a train of constant-amplitude spikes, with the firing rate proportional to the amplitude of the motion at the IHC's frequency-specific location.
This is illustrated below, where the violet waveform represents a varying-amplitude sine wave at the specific frequency of an IHC. The green spike train has a constant amplitude, but its spike rate is proportional to the sound amplitude:
At another sound frequency this neuron might fire only rarely, since the basilar membrane would not vibrate at this particular IHC position. But another IHC would be excited instead, producing spikes on its own dedicated neuron.
Each sound frequency thus has a separate neural pathway that sends its amplitude to the brain, so it doesn't need to send frequency information... the frequency is encoded by the position of the IHC and hence its particular output neuron. This is called the place principle, or sometimes the labeled line theory.
Think of a piano, where there are separate keys for each note. All keys behave basically the same, each key mechanism (IHC) conveying only information about how hard it has been hit (amplitude) to the mechanical linkage (neuron to brain) that eventually results in sound production (perception). The basic pitch of the sound is determined by which key is hit, not by how hard it is hit.
The above spectrum has only 512 frequency positions, while the ear has about 3500 IHCs to provide much finer frequency resolution. At the low frequencies in the above missing fundamental example, the filtering is so selective that each harmonic would excite a different IHC, corresponding to the distinct peaks in the spectrum. This sharp filtering means that each IHC would see a near-sinusoidal waveform, not the total multi-component waveform with periodicity corresponding to the missing fundamental. The IHC tuned to the fundamental frequency would thus only be excited when that frequency was actually present.
But without the periodicity, how could the brain perceive a missing fundamental?
In principle, some sort of mechanical distortion in the excitation of the basilar membrane could cause a distortion product at the missing fundamental frequency. This explanation was ruled out by experiments conducted over 60 years ago. Masking noise was introduced that would have overwhelmed any such distortion product, yet perception of the missing fundamental was not blocked.
However, even without waveform periodicity, the place principle alone can, in many circumstances, explain the missing fundamental through pattern recognition... something the brain excels at. Consider that the auditory system, with a separate neural pathway for each pitch it can detect, is similar to the visual system with a separate pathway from each retinal cell for each image pixel the eye can detect. The visual system can recognize the letter 'A', for example, even when much of it is missing:
The brain learns to associate a certain pattern of neural activity with a certain shape or sound. It can then make that same association even if the pattern isn't complete, as long as certain critical elements are present.
This place or spectral theory explanation is fairly well accepted for low frequencies, as in our example here. However, it has difficulties explaining certain observations, such as listeners that can hear the missing fundamental even when only a few upper harmonics are present that are so high in frequency that they are not well separated by the cochlear filtering process.
Also, the missing fundamental effect can be changed by manipulating the relative phases of the harmonics. This changes the waveform peaks but does not affect the spectrum, so presumably would not be detectable via place theory. (See the Phase Experiments subtopic.)
These and other auditory phenomena point toward a temporal theory, which uses waveform periodicity.
But wait, didn't we lose that periodicity information when the sound was filtered into separate neurons for each frequency? Well, not quite. If each neuron encodes the phase of the frequency component along with its amplitude, there is theoretically enough information for the brain to reconstruct the original waveform, including its periodicity. This is similar to the way an inverse Fourier transform can reconstruct a waveform from a spectrum.
It turns out that this phase information is indeed preserved to a large extent, although in a statistical fashion. As noted, the firing rate of each neuron encodes the amplitude of the filtered input waveform, but the maximum firing rate is much too low to encode the complete filtered IHC waveform, which is itself in the same frequency range. In fact, it's even too low to fire once per cycle in many cases.
But when the neuron is able to fire at all, it tends to fire at a peak in the incoming IHC waveform; if it can't respond to the current peak, it responds to the next one, or the one after that. The average firing rate would thus be some sub-multiple of the true IHC input frequency, but it would still be phase locked with respect to the IHC sine wave.
If the brain can keep track of the relative phase across neuron outputs for multiple harmonics, it might be able to reconstruct the original overall waveform, and hence determine the period.
One signal processing technique that can determine the period from the overall waveform is known as autocorrelation. Computationally, this typically requires an array of time delays, although no such structures have yet been identified in the auditory system.
In the case of poorly-separated ("unresolved") upper harmonics, a single IHC is exposed to multiple harmonics. It thus sees a waveform with peaks at the same period as the fundamental, and its neural output would thus show that periodicity.
This is essentially the same phenomenon as auditory "beats" when only two components are present. You can explore this by setting Total Harmonics to 2 and setting Fundamental and Lowest Harmonic so that their product is in the 1000 Hz range or above. You might want to set Continuous Tone mode to get clean waveform triggering.
The lowest Fundamental frequency you can set this way is 10 Hz. Alternatively, the Monaural and Binaural Beats (Beats_Demo) mini-app allows you to set its Difference Frequency (which is equivalent to the missing fundamental) as low as you want, although it is limited on the high end to 100 Hz. Click the Mode: Binaural button to Mode: Monaural. Set the Center Frequency to 1000 Hz and the Difference Frequency as desired.
With either of the above approaches (but especially with Beats_Demo), note that at very low "beat" or "fundamental" frequencies, such as a few hertz, you perceive waveform periodicity as discrete, countable events. At 10 Hz the beat rate is just barely countable, but if you go much beyond that it becomes "roughness", and as you go higher still it eventually becomes a true pitch. If you move the Center Frequency or Lowest Harmonic down to more-typical musical ranges and repeat the above, you'll notice that the roughness is more likely to be heard as a deep fundamental... a gut-rumbling super-low organ note, for example.
This may indicate that beats, roughness, and the missing fundamental are all part of the same general phenomenon, which would point to a temporal theory. The current consensus seems to be that both spectral and temporal theories are involved. The paper on lateral Heschl's gyrus by Schneider, Sluming, et.al. reports that they "found a strong neural basis of both types of pitch perception, which corroborated the functional specialization of left auditory cortex for rapid temporal and the right hemisphere for spectral processing." (See the External References and Links section, below, for the full citation and a link to the PDF of this paper.)
The above Auditory Theories section discusses two different ways the missing fundamental might be detected by the ear-brain system. The place (spectral) theory would seem to require only the presence of the harmonic component frequencies at their respective spectral positions on the basilar membrane; the temporal theory would seem to require detectable waveform peaks. The available evidence indicates both processes contribute to the phenomenon.
One approach that might shed information on the contributions of each type of process is to manipulate the relative phases of the individual components to maximize or minimize waveform peaks.
Assuming the individual components are well-separated on the basilar membrane, the sharp tuning should insure that phase does not affect the amplitude of vibration at the location of any frequency component. If so, place-based processing should not be affected by relative phase shifts.
On the other hand, since phase changes can affect the size and placement of waveform peaks, we expect they might affect temporal processing.
The Missing Fundamental mini-app has a phase mode button that defaults to Zero Phase. In this mode all harmonics start at the same phase and thus produce strong peaks in the overall waveform at the missing fundamental periodicity.
The relative "peakiness" is given by the crest factor (CF), which is the ratio of the peak amplitude to the RMS average over one waveform period. Show Values reports CF values as dB, shown beneath the harmonic lists for each tone in Waveform Display mode only. For the default parameters at Zero Phase, the CF for the A tone is 8.022 dB and for the B tone it is 8.410 dB:
When you change any parameter you will notice that the Show Values display is updated immediately, including the CF for tone A, but the B CF vanishes briefly and is updated with the new value a moment later. That's because these CFs are actual measured values, and the _Miss_Fund_Crest task must wait for the B tone to sound before it can be measured.
Clicking Zero Phase button to +/- Phase Factor enables the Phase Factor, deg/N control. This applies the specified phase shift (45 degrees default) times the harmonic number to each B component (or to all, in Continuous Tone mode), with the sign alternating between positive on even harmonics and negative on odd. In the default case with Fundamental OFF and the B tone having harmonics 3-6 the phase is:
N Hz Deg 5A 550.000 0.000 4A 440.000 0.000 3A 330.000 0.000 2A 220.000 0.000 1A (110.000) 0.000 CF 8.022 dB 6B 550.000 0.000 5B 458.333 270.000 4B 366.667 0.000 3B 275.000 90.000 1B (91.667) 0.000 CF 5.044 dB
The default of 45 degrees per harmonic gives the lowest B crest factor with the default parameters; this will still hold true if you change the Fundamental frequency, but not if you change Lowest Harmonic Number or Total Harmonics, or toggle Fundamental OFF to Fundamental ON, or change Harmonic A-B Increment.
In general, you should start at 45 and slowly work down while watching the CF for tone B. CF values are not shown in Fundamental ONLY mode. They are also not shown in Fundamental OFF, STEP mode, but in that case they are the same as the default Fundamental OFF mode since the only thing changing is the fundamental frequency.
Note that since the A and B tones use the same top harmonic component (550 Hz here), Phase Factor can't apply the computed phase directly to B without changing A. Instead, it forces the top phase to zero (to match the A tone) and adjusts all the lower harmonics (and the fundamental, if Fundamental ON is active) to have the same relative phases as computed by the above relationship. The resulting waveform is identical, just shifted in time. (No such adjustment is needed in Continuous Tone mode since there is no shared harmonic.)
Below is the resulting waveform, compared to the default Zero Phase. There is a substantial reduction in peakiness of the Phase Factor waveform. Although not shown, the spectra and spectrograms of the two are identical. However, to the author's ears, the default Zero Phase has a strong high-low pitch drop, while the Phase Factor version is a mild low-high pitch rise. (This effect may be best heard on headphones.)
You can toggle back and forth to compare; to go back to Zero Phase, hold down the SHIFT key while clicking the Phase Factor button. Then release the SHIFT key while clicking to return to Phase Factor.
This directional change seems to indicate that periodicity plays a role in at least some conditions, with some observers. There is plenty of territory to explore here; this might be fruitful area for a science fair project, undergraduate thesis, or graduate research.
See also the Phase Audibility Demonstration mini-app for related experiments.
If you click Phase Factor again it advances to Minimum-Peak Phases. This mode applies the Newman algorithm discussed in Multitone Signals with Low Crest Factor by Boyd. (See External References and Links, below.) Although this may be an optimal algorithm for signals with many tones that form a gap-free harmonic series, it is usually not as good as the above +/-Phase Factor method for missing fundamentals with small numbers of harmonics as used here. The Minimum-Peak method gives a CF of 6.030 dB for the B tone with default parameters, compared to 5.044 dB for Phase Factor as seen above.
It is even worse with Total Harmonics reduced to 3 and Fundamental ON, giving a CF of 8.572 dB compared to 5.053 for the best Phase Factor of 34 deg/N.
In Continuous Tone mode, however, with Total Harmonics set to 7 (maximum) and Lowest at 2 with Fundamental ON to form an unbroken series from 1 to 8, it gives a CF of 5.413 dB; slightly besting the optimum Phase Factor CF of 5.687 dB with Factor at 44 deg / N.
If you have a different algorithm you'd like to use, you can replace the Newman formula. See Custom Phase Algorithm, below.
Another click on the phase button moves from Minimum-Peak to Random Phases, which also enables the Randomize Phase button below it). Random Phases sets the phases of the B components to pseudo-random values, which were stored as an array of constants when the Missing_Fundamental macro started up.
The array can be replaced with a new set of random values by clicking Randomize Phase; otherwise, the same values are used whenever Random Phases is active. This allows you to compare a particular set of random phases with any of the other phase modes.
The pseudo-random number generator seed that is used to create the random phases is stored in VarP, which is saved across Daqarta sessions. This value is set when you hit Randomize Phase. It is used to set the seed for the default random phases created when Missing_Fundamental starts. This means that if you find a set of random phases that you want to keep using, you will be able to use them in future sessions as long as you do not hit Randomize Phase.
If you want to try other random phases, but still be able to return to a prior set, you need to save the seed. One way to do that would be to modify _Miss_Fund_Ctrls by uncommenting the Field1 line:
IF.Ctrls=9 VarP=Posn?r ; Field1=VarP(0)
Now when you find a seed you want to save, you can copy Field1 and paste it into a Windows Notepad file, or you can save up to about 200 seeds in Daqarta's Notes for later copy to a final destination.
Although it may seem like Zero Phase always gives the largest crest factor (largest waveform peaks), that isn't the case. A few minutes spent clicking the Randomize button should demonstrate that you can get up to about 1 dB higher CF, especially with Fundamental OFF.
If you have (or are developing) an algorithm for picking phases, you can replace the Newman approach used for Minimum-Peak Phases. There are 3 places the Newman formula is used in Miss_Fund_Update: for the A tone (if QP = 1 or 3 near the start of Missing Fundamental, for the B tone, and for Continuous Tone mode. The latter code is simplest:
IF.Btn3=2 P=(180 * (UH - 1)^2 / UN) % 360 ENDIF.
Here UH is the harmonic number, UN is the total number of harmonics plus the fundamental (if Fundamental ON), and the computed phase P is in degrees. (The % 360 modulus operation at the end is not part of the original algorithm; it just keeps results in a manageable 0-360 degree range for display purposes.) Note that the fundamental (UH = 1) phase is always 0.
The A and B tones are complicated by the need to force both top harmonics to 0, since a single Generator stream (R.3) is used for both. This involves using the Newman algorithm to compute the phase Q for each top harmonic (which will be different since A and B have different top harmonic numbers, even though the frequencies are the same). Q is the phase that would have been used for this harmonic according to the formula, but since we will be forcing this to 0 it must be used to compensate each lower harmonic phase P.
The correction factor is the ratio of the lower harmonic number over the top harmonic number, times Q.
For the A tone, the code is:
IF.UP=2 Q=180 * (Buf0 - 1)^2 / UN P=((180 * (UA - 1)^2 / UN) - UA / Buf0 * Q) % 360 ENDIF.
Here Buf0 holds the top harmonic number and UA is the current harmonic number whose phase is being computed.
The B tone code is similar, except the top harmonic number is in Buf0 and UB is the current harmonic number:
IF.UP=2 Q=180 * (Buf0 - 1)^2 / UN P=((180 * (UB - 1)^2 / UN) - UB / Buf0 * Q) % 360 ENDIF.
You only need to replace the B code if you are working exclusively in Two-Tone mode.
Alternatively, if you have specific phases you want to use, you can replace the array of random values used by the Random Phases option. Do this in the main Missing_Fundamental code, right after the part where the array is filled:
Posn#r=VarP QI=0 WHILE.QI=<8 Buf0[QI]=rnd(0,360) QI=QI+1 WEND.
This is where the random values are set into Buf0 to Buf0 for later use by Random Phases. You can leave this intact and just insert your new code right after it, overwriting the pre-set values.
Your added code will look like this, but with your values replacing the 350, etc:
Buf0=350.000 ;5B Buf0=240.000 ;4B Buf0=130.000 ;3B
The above assumes you are using Lowest Harmonic = 2, Total Harmonic = 4, and 1-Harmonic A-B Increment settings (defaults). In this case, the top B harmonic will be 6B; the top harmonic phase in Two-Tone mode is always 0, so you don't set anything for that component.
If you reduce Total Harmonics to 3, only 4B and 3B (Buf0 and Buf0) need to be set this way; the top harmonic will be 5B, but will automatically use 0 instead of Buf0. Fundamental ON will always use Buf0 as the random 1B phase.
If you increase Lowest Harmonic to 3, all the above harmonic numbers will increase to match. Note that 'Lowest' refers to the A harmonics; the lowest B harmonic will be higher by the Harmonic A-B Increment. If the Increment is 1, then the B harmonics will run from 4 to 7 instead of 3 to 6, but the Buf0 indices are unchanged: Buf0 is still the next-to-highest as long as Total = 4.
If you have modified the QB=2 line near the start of Missing_Fundamental to allow phase changes to apply to A only (QB=1) or to both A and B (QB=3), and you want to set specific Random Phases values for A, the comparable Buf0 index values are 7, 6, and 5. The A fundamental is always on Buf0 when Fundamental ON is active.
Random Phases can also be applied to Continuous Tone mode. With Lowest = 2, and Total = 7, the harmonics run from 2 to 8 and the corresponding Buf0 indices run from 0 to 6. Buf0 is never used in Continuous mode; if Fundamental ON is active, it is always set to 0 phase.
Schneider, P., Sluming, V., Roberts, N., Scherg, M., Goebel,
R., Specht, H., Dosch, H.G., Bleeck, S., Stippich, C., Rupp,
A., "Structural and functional asymmetry of lateral
Heschl's gyrus reflects pitch perception preference".
Nature Neuroscience, volume 8, number 9, September 2005,
Boyd, S., Multitone Signals with Low Crest Factor,
IEEE Transactions On Circuits And Systems, volume CAS-33,
number 10, October 1986, pages 1018-1022.
Newman, D., An L1 Extremal Problem For Polynomials,
Proc. Amer. Math. Soc., volume 16, Dec 1965, pages
Steve Mould - Science Presenter:
Index Use 0-7 Random harmonic phases 8 A top harmonic number 9 B top harmonic number 10-17 Continous tone harmonic numbers 19 B fundamental frequency 20-24 A harmonic numbers 25-29 B harmonic numbers 30-37 Continuous tone harmonic phases 40-44 A harmonic phases 45-48 B harmonic phases 50 Crest factor task status 51 A crest factor, dB 52 B crest factor, dB 53 Continuous tone CF, dB 57 Btn7 prior state save during Play Music 58 Btn7 single-time Play Music tip flag 100-103 "-Harmonic A-B Increment" text string 104-107 "-Harmonic Increments" text string 900-999 Buf0#Bs=9 Block Save during Play Music
;<Help=H4913 R=15m ;Rise/Fall times for A/B two-tone test H=300m ;On (High) time per tone G=0 ;Gap between A and B tones C=1000m ;Cycle time for 2 tones plus silence QX=0 ;QX=1 to eXchange A,B order to B,A QP=2 ;Phase change only on B (1=A, 3=both) U1=1 ;A harmonic increment U2=1 ;B harmonic increment UW=0 ;0=Sine, 1=Tri, 2=Ramp, 3=Sqr, 4=Pulse W=4 ;Sweep limit freq = W times fundamental QN=12 ;Frequency steps in above sweep range Close= ;Close any open data file Decimate=0 ;Decimate off Sgram=0 ;Spectrogram off PitchTrk=0 ;Pitch Track off Spect=0 ;Spectrum off Xpand=0 ;No X-axis expand SpectWindOn=1 ;Spectrum window on E.IF.Input= ;If Input is enabled, Input=0 ;Force Input off ENDIF. TrigMode=GenSync ;Set to Generator sync Trig=1 ;Trigger on TraceUpdate=10 ;10 ms per trace update A.LoadGEN="MissFund" ;Load Generator setup, no prompt Ctrls="<<Missing Fundamental" ;Custom Controls dialog title Ctrl0="<<Fundamental, Hz" ;Ctrl0 title Ctrl0="<S(10,4000)" ;Slider, 10-4000 Hz Ctrl0="<p(3)" ;3 decimal places Ctrl0=110 ;110 Hz default Ctrl1="<<Lowest Harmonic Number" Ctrl1="<S(2,16)" ;Lowest harmonic 2-16 Ctrl1="<p(0)" Ctrl1=2 ;2nd harmonic default Ctrl2="<<Phase Factor, deg/N" Ctrl2="<S(0,360)" Ctrl2="<D" ;Disable, Btn3 enables Ctrl2=45 ;45 degrees/harmonic Ctrl3="<<Total Harmonics" Ctrl3="<S(1,7)" ;Allow 1-7 harmonics Ctrl3="<p(0)" Ctrl3=4 ;4 default Btn0="Fundamental OFF" Btn0="<M(3)" ;Multi-state button, 0-3 Btn0=0 ;Default = OFF Q0=0 ;Saves prior state for reverse Buf0#a4="-Harmonic A-B Increment" ;Label tail, default 2-tone mode Buf0#a4="-Harmonic Increments" ;Label tail, Continuous mode Btn1="1" + Buf0(a4) ;"1-Harmonic A-B Increments" default Btn1="<M(3)" ;1,2,3,4-harmonic increments Btn1=0 ;Default to 1- Btn2="Calibrate Level" ;Changes to Equal vs 1/N if Continuous Btn2="<T" ;Simple on/off Toggle button Btn2=0 ;Default to off (two-tone) Q2=0 ;Default to Equal for Continuous M=1 ;Level factor, reduced for Calibrate Btn3="Zero Phases" Btn3="<M(3)" ;Multi-state button, 0-3 Btn3=0 Btn4="Show Values" ;Toggles meter display Btn4="<T" Btn4=0 Btn5="Randomize Phase" Btn5="<M" ;Momentary pushbutton Btn5="<D" ;Disable, Btn3 enables when Random Btn5=0 Btn6="Waveform Display" ;Toggle to Spectrum or Spectrogram Btn6="<M(2)" ;Multi-state button, 0-2 Btn6=0 Btn7="Two-Tone Mode" ;Toggle to Continuous or Music Btn7="<M(2)" ;Multi-state button, 0-2 Btn7=0 Buf0=0 ;Saves prior state during Music Buf0=0 ;Set to 1 after Play Music tip IF.UW=>0 ;Wave other than default Sine? IF.UW=>4 ;Limit to 4=Pulse max UW=4 ENDIF. UI=0 ;Start with Stream 0 = L.0. WHILE.UI=<8 ;Set all 8 streams to new Wave Ch=UI ;Stream (channel) number Ch.Wave=UW ;Set Wave type for stream UI=UI+1 ;Next stream WEND. ENDIF. K=2*R + H + G ;Min Burst Cycle time IF.C=<2 * K ;2 bursts / overall cycle C C=2 * K ;Increase C as needed ENDIF. IF.QX=0 ;Default A,B burst order? A=0 ;A starts with no Lag B=K ;B starts after A complete QA="A" ;Label for 1st burst QB="B" ;Label for 2nd burst ELSE. ;Else reverse B,A order B=0 ;B starts with no Lag A=K ;A starts after B complete QA="B" ;1st burst called "B" QB="A" ;2nd burst called "A" ENDIF. UI=0 WHILE.UI=<7 ;Set streams 0-6 Ch=UI ;Stream (channel) number Ch.BurstRise=R Ch.BurstHigh=H Ch.BurstFall=R IF.UI=<4 ;Streams 0-3 are 2nd burst Ch.BurstLag=B ELSE. ;Streams 4-6 are 1st burst Ch.BurstLag=A ENDIF. Ch.BurstCycle=C ;Total Cycle for each burst Ch.TrainCycle=C UI=UI+1 WEND. R.3.BurstLag=0 ;Stream 7 is double burst, no Lag R.3.BurstRise=R R.3.BurstHigh=H R.3.BurstFall=R R.3.BurstCycle=K ;Set each burst cycle to min R.3.TrainLag=0 R.3.TrainCount=2 ;2 bursts per train R.3.TrainCycle=C ;Overall 2-burst train cycle Gen=1 ;Start sound RO.Disp=0 ;No Right Out display (=Left) Posn#r=VarP ;Repeatable random seed QI=0 WHILE.QI=<8 Buf0[QI]=rnd(0,360) ;8 random phases in Buf0 QI=QI+1 WEND. Mtr0="<<Harmonic Components" ;Mtr0 title Mtr0="<C(ColorNum?l)" ;Mtr0 text color of Left Out Mtr0="<B(ColorNum?S)" ;Background color of screen Mtr0="<F(30)" ;30-pixel default font height Mtr0="<f(3)" ;Lucida Console font family @_Miss_Fund_Ctrls=Ctrls ;Set Custom Controls macro Task="-_Miss_Fund_Mtr" ;Remove Mtr0 task Task="-_Miss_Fund_Crest" ;Remove crest factor task IF.Buf0=>1 ;Play Music active? PitchMIDI=0 ;Stop playing if so PitchMIDIdlg=0 ;Close Pitch-to-MIDI dialog PitchTrk=0 ;Stop pitch tracking SgramDlg=0 ;Close Sgram/PT dialog Gen=1 ;Gen on for RO.Disp re-enable ENDIF. RO.Disp=1 ;Restore Right Out display Decimate=0 ;Decimate off, if on Sgram=0 ;Spectrogram off, if on Spect=0 ;Spectrum off, back to waveform Trig=1 ;Trigger on Gen=0 ;Generator off on exit Msg= ;Remove 2-tone CAL message Msg="<<" Mtr0= ;Meter off Mtr0="<f(2)" ;Arial font family
;<Help=H4913 IF.(2 * Btn7 + Btn2)=!1 ;If not 2-tone CAL mode, Msg= ;Remove calibration message Msg="<<" ENDIF. IF.Ctrls=0 ;Ctrl0 = Fundamental freq? @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=1 ;Ctrl1 = Lowest Harmonic? Ctrl1=cint(Ctrl1) ;Convert to integer @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=2 ;Ctrl2 = Phase Factor? @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=3 ;Ctrl3 = Total Harmonics? Ctrl3=cint(Ctrl3) ;Convert to integer IF.Btn7=0 ;Two-tone mode? IF.Ctrl3=>4 ;Limit to 4 harmonics max Ctrl3=4 Msg="<<Too Many Harmonics!" Msg="4 Harmonics MAX in Two-Tone mode." ENDIF. IF.Ctrl3=4 ;If 4-harmonic two-tone, IF.Btn0=1 ;No 'Fundamental ON' Btn0=0 Btn0="Fundamental OFF" ENDIF. ENDIF. ENDIF. @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=4 ;Btn0 = Fundamental OFF, ON, etc? TrigMode=GenSync IF.Btn0=1 ;If ON attempted IF.(!Btn7 && int(Ctrl3>>2))=1 ;In 4 harmonic 2-tone mode IF.Q0=0 ;Prior = OFF? (normal) Btn0=2 ;Ahead to ONLY ELSE. ;Prior = ONLY (w.SHIFT) Btn0=0 ;Back to OFF ENDIF. ELSE. ;Else set Level in _Update Btn0="Fundamental ON" ENDIF ENDIF. IF.Btn0=0 ;If OFF, Btn0="Fundamental OFF" L.0.Level=0 ;Set Level to 0 ENDIF. IF.Btn0=2 ;If ONLY, Btn0="Fundamental ONLY" L.0.Level=100 ;Set Level to 100% ENDIF. IF.Btn0=3 ;STEP / SWEEP mode? TrigMode=Norm IF.Btn7=1 ;Continuous tones? Btn0="Fundamental OFF, SWEEP" ELSE. ;Else 2-tone burst mode Btn0="Fundamental OFF, STEP" ENDIF. Task="_Miss_Fund_Mtr" ;Meter task tracks progress ELSE. Task="-_Miss_Fund_Mtr" ;Else meter change on Update ENDIF. Q0=Btn0 ;Save for prior state if SHIFT @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=5 ;Btn 1 = Harmonic Increment? UH=Btn1+1 ;Harmonic number 1-4 Btn1="" + UH + Buf0[100 + 4 * Btn7](a4) ;Label Btn1 @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=6 ;Btn2 = Calibrate / Level? IF.Btn7=1 ;Continuous tone mode? IF.Btn2=0 Btn2="Levels EQUAL" ELSE. Btn2="Levels 1 / N" ENDIF. Q2=Btn2 ELSE. ;Calibrate if 2-tone mode IF.Btn2=0 ;If calibrate off, M=1 ;Level factor = 1 ELSE. ;Else calibrate ON M=10^(-50/20) ;Factor = -50 dB GenVolDlg=1 ;Show F9 volume ctrls Msg="<<Level Calibration:" Msg="Adjust volume until you can just" _ +n + "detect the tones, then toggle Calibrate" _ +n + "off for 50 dB SL Two-Tone test." ENDIF. ENDIF. @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=7 ;Btn3 = Phase Mode? IF.Btn3=0 ;Set all phases to 0? Btn3="Zero Phases" Ctrl2="<D" ;Disable Phase Factor Btn5="<D" ;Disable Randomize Phase ENDIF. IF.Btn3=1 ;Phase Factor? Btn3="+/- Phase Factor" Ctrl2="<N" ;Enable control Btn5="<D" ;Disable Randomize Phase ENDIF. IF.Btn3=2 ;Minimum phase? Btn3="Minimum-Peak Phases" Ctrl2="<D" ;Disable Phase Factor Btn5="<D" ;Disable Randomize Phase ENDIF. IF.Btn3=3 ;Random Phases? Btn3="Random Phases" Ctrl2="<D" ;Disable Phase Factor Btn5="<N" ;Enable Randomize Phase ENDIF. @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=8 ;Btn4 = Show Values? Mtr0= ;Clear meter display IF.Btn4=0 ;Show Values now OFF? Task="-_Miss_Fund_Crest" ;Remove crest factor task ELSE. ;Else Show Values is ON Buf0=3 ;Block crest factor updates Task="_Miss_Fund_Crest" ;Install crest factor task Mtr0="<H4913" ;Set Meter Help to enable @_Miss_Fund_Update ;Update waves (and meter) ENDIF. ENDIF. IF.Ctrls=9 ;Btn5 = Randomize Phase? VarP=Posn?r ;Save random seed ; Field1=VarP(0) ;Copy to Field1 QI=0 WHILE.QI=<8 ;For each of 8 components Buf0[QI]=rnd(0,360) ;Set random 0-360 deg QI=QI+1 WEND. @_Miss_Fund_Update ;Update waves (and meter) ENDIF. IF.Ctrls=10 ;Btn6 = Waveform/Spectrum/Sgram IF.Btn6=0 Btn6="Waveform Display" Trig=1 Decimate=0 Spect=0 Sgram=0 ENDIF. IF.Btn6=1 Btn6="Spectrum Display" Trig=0 Spect=1 Ylog=1 Xlog=1 ENDIF. IF.Btn6=2 Btn6="Spectrogram Display" Trig=0 Sgram=1 Xpand=1 YlogTop=0 ;0 dB top color TraceMag=8 ;-40 dB range ENDIF. @_Miss_Fund_Update ENDIF. IF.Ctrls=11 ;Btn7 = Two-Tone/Continuous/Music? IF.Buf0=0 ;Tip message given yet? Buf0=1 ;Don't show it again Msg="<<TIP:" ;Title for message Msg="ALT+Click to Play Music" ENDIF. U7=Buf0 ;Prior Btn7 state before click IF.U7=>1 ;Was it Play Music? (2 or 3) Buf0=U7 & 1 ;Back to 0 or 1 Btn7=Buf0 ;New Btn7 state Buf0#Br=9 ;Restore variables from Block 9 PitchMIDI=0 ;Stop playing PitchMIDIdlg=0 ;Close Pitch-to-MIDI dialog PitchTrk=0 ;Stop pitch tracking Sgram=0 ;Sgram/PT OFF SgramDlg=0 ;Close Sgram/PT dialog Gen=1 ;Generator ON IF.Btn6=0 ;Wave Display? Trig=1 ;Triggered if so ELSE. IF.Btn6=1 ;Spectrum? Spect=1 ELSE. ;Else Spectrogram Sgram=1 ENDIF. ENDIF. Ctrl0="<N" ;Enable other controls Ctrl1="<N" IF.Btn3=1 ;If Btn3 = Phase Factor Ctrl2="<N" ;Re-enable it ENDIF. Ctrl3="<N" Btn0="<N" Btn1="<N" Btn2="<N" Btn3="<N" Btn4="<N" IF.Btn3=3 ;If Btn3 = Random Phases Btn5="<N" ;Enable Randomize ENDIF. Btn6="<N" IF.Btn7=0 ;Replace "Play Music" label Btn7="Two-Tone Mode" ELSE. Btn7="Continuous Tone" ENDIF. @_Miss_Fund_Update ;Update waves (and meter) ELSE. ;Wasn't Play Music IF.Key?$=2 ;ALT-key down? Buf0=U7 | 2 ;Set Play Music state Btn7=2 Buf0#Bs=9 ;Save variables to Block 9 Btn7="Play Music" ;Re-label button Mtr0= ;Remove meter display Gen=0 ;Generator OFF Trig=0 ;Trigger OFF Decimate=0 ;Decimate OFF Sgram=1 ;Sgram/PT ON SgramDlg=1 ;Show Sgram/PT dialog XpandMax=2531.25 ;Set vertical range XpandMin=46.875 Xpand=1 PitchShow=2 ;Show MIDI Note / Inst PitchWide=1 ;Show wide pitch track PitchYaxis=0 ;Show notes on Y axis PitchSteps=1 PitchMIDIdlg=1 ;Open Pitch-to-MIDI dialog A.LoadDQM="MissFundamental" ;Auto-load Daqmusiq setup PitchTrk=1 ;Start pitch tracking PitchMIDI=1 ;Start playing Ctrl0="<D" ;Disable all other controls Ctrl1="<D" Ctrl2="<D" Ctrl3="<D" Btn0="<D" Btn1="<D" Btn2="<D" Btn3="<D" Btn4="<D" Btn5="<D" Btn6="<D" ELSE. ;Toggle Two-Tone / Continous Buf0=Buf0 # 1 ;Flip between 0 and 1 Btn7=Buf0 ;Set new button state IF.Btn7=0 ;Two-Tone mode? Btn7="Two-Tone Mode" ;Label button IF.Btn0=3 ;STEP or SWEEP mode? Btn0="Fundamental OFF, STEP" ;Use STEP for 2-tone ENDIF. IF.Ctrl3=>3 ;Total harmonics more than 3? Ctrl3=4 ;Limit to 4 max IF.Btn0=1 ;If Fundamental ON now, Btn0=0 ;Force it OFF Btn0="Fundamental OFF" ENDIF. ENDIF. Q2=Btn2 ;Save continuous Level state Btn2="Calibrate Level" ;Change button usage for 2-tone Btn2=0 ;Force Calibrate off M=1 ;Unity Level factor ELSE. ;Going to Continuous mode Btn7="Continuous Tone" ;Label button IF.Btn0=3 ;STEP or SWEEP mode? Btn0="Fundamental OFF, SWEEP" ;Use SWEEP for Continuous ENDIF. Btn2=Q2 ;Restore saved Level state IF.Q2=0 ;Set corresponding label Btn2="Levels EQUAL" ELSE. Btn2="Levels 1 / N" ENDIF. ENDIF. UH=Btn1+1 ;Harmonic number 1-4 Btn1="" + UH + Buf0[100 + 4 * Btn7](a4) ;Label Btn1 @_Miss_Fund_Update ;Update waves (and meter) ENDIF. ENDIF. ENDIF.
;<Help=H4913 GenUpdate=0 ;No Generator restarts F=Ctrl0 * (Ctrl1 + Ctrl3 - 1) IF.Btn0=3 ;SWEEP / STEP mode? UN=Ctrl3 ;Total Harmonics, no fundamental UX=1 ;Will set Sweep on IF.Btn7=1 ;Continuous (not two-tone)? S=QN * C ;Sweep length = #steps * step time QX=0 ;No Stairs (continuous sweep) ELSE. ;Else two-tone mode S=C ;Sweep length for one step QX=QN ;Number of Stairs ENDIF. F=F * W ELSE. ;Else Fundamental OFF, ON, ONLY UN=Ctrl3 + Btn0 ;Total Harmonics + Fundamental if ON UX=0 ;No Sweep ENDIF. IF.Btn6=>0 ;Spectrum or Spectrogram display? X=cint(SmplRate / (F * 8)) IF.X=>1 Decimate=1 DecX=X ELSE. Decimate=0 ENDIF. XpandMax=1.2 * F ENDIF. UI=0 WHILE.UI=<8 ;Set Sweep paramters for all streams Ch=UI ;Set stream (channel) number Ch.Sweep=UX ;Sweep on/off Ch.SweepLength=S ;Duration Ch.SweepStairs=QX ;Number of stairs, else 0=continuous UI=UI+1 WEND. IF.Btn7=0 ;Default two-tone mode? UC=0 ;Meter update count UA=(Ctrl3 - 1) * U1 + Ctrl1 ;Top A harmonic # UB=(Ctrl3 - 1) * U2 + Ctrl1 + Btn1 + 1 ;Top B harmonic # Buf0=UA Buf0=UB B=Ctrl0 * UA / UB ;B fundamental freq Buf0=B ;Store for meter IF.Btn0=2 ;Fundamentals ONLY? R.0.ToneFreq=Ctrl0 ;A params on Right 0 R.0.SweepEnd=Ctrl0 * W ;Fundamental * factor R.0.Level=100 R.0.Burst=1 L.0.ToneFreq=B ;B params on Left 0 L.0.SweepEnd=B * W L.0.Level=100 * M L.0.Burst=1 UI=1 WHILE.UI=<4 ;All upper streams off Ch=UI ;Left stream Ch.Level=0 Ch=UI + 4 ;Right stream Ch.Level=0 UI=UI + 1 WEND. ELSE. ;Else OFF, ON, or STEP UI=Ctrl3 ;Total A (or B) harmonics UJ=UI ;Default A loop index IF.Btn0=1 ;If Fundamental ON, UJ=UI+1 ;Include extra loop pass ENDIF. L=(100 / UN) * M ;100% / components * CAL factor Ch=7 IF.QP=2 ;Phase change only on B? UP=0 ;Zero phase here if so ELSE. ;Else 1 = A only, 3 = both UP=Btn3 ;Use Btn3 as-is ENDIF. WHILE.UJ=>0 ;Do total A (or B) harmonics IF.UI=0 ;Last pass (A Fundamental)? UA=1 ;Fund = "1st harmonic" Ch=4 ;Always R.0. channel ENDIF. F=Ctrl0 * UA ;Fundamental * harm number IF.Btn0=3 ;If STEP, UF=F * W ;Use max freq as limit ELSE. UF=F ;Else current freq ENDIF. IF.UF=<SmplRate/2 ;Freq in audible range? Ch.ToneFreq=F ;Set output freq if so Ch.SweepEnd=F * W ;End freq for STEP mode IF.UP=0 ;Zero phase? P=0 ;Set harmonic phase ENDIF. IF.UP=1 ;Phase Factor? US=1 - (Buf0 & 1) * 2 ;A top, alt sign Q=Ctrl2 * Buf0 * US ;A top phase = ref US=1 - (UA & 1) * 2 ;Harmonic alt sign P=(Ctrl2 * UA * US - UA / Buf0 * Q) % 360 ENDIF. IF.UP=2 ;Min Peak? Q=180 * (Buf0 - 1)^2 / UN ;Newman top phase P=((180 * (UA - 1)^2 / UN) - UA / Buf0 * Q) % 360 ENDIF. IF.UP=3 ;Random? IF.UA=Buf0 ;Top A harmonic? P=0 ;Phase = 0 ELSE. P=Buf0[UI+3] % 360 ;Pre-stored rand phase ENDIF. ENDIF. IF.P=<0 ;Neg phase? P=P + 360 ;Pos equivalent ENDIF. Ch.TonePhase=P ;Set output phase Buf0[40 + UI]=P ;Store phase for Mtr Buf0[20 + UI]=UA ;Store harmonic num Ch.Burst=1 ;Burst ON Ch.Level=L ;Set level ELSE. ;Else if freq too high, Ch.Level=0 ;Set to silence Buf0[20 + UI]=0 ;Store for Mtr ENDIF. UA=UA - U1 ;Next-lower harmonic Ch=Ch - 1 ;Next-lower stream UI=UI - 1 ;Next-lower harm index UJ=UJ - 1 ;Next-lower loop index WEND. ;Do all Total harmonics IF.Btn0=0 ;Fundamental OFF? Buf0=0 ;Set phase = 0 ENDIF. UI=7 - Ctrl3 WHILE.UI=>3 ;If Total was less than 4... Ch=UI Ch.Burst=0 ;Set remaining to silence Ch.Level=0 UI=UI - 1 WEND. ;Do all A components Buf0[25 + Ctrl3]=UB ;Save B top harmonic number Buf0[45 + Ctrl3]=0 ;Phase always zero UI=Ctrl3 - 1 ;Top harm shared, no dup UJ=UI ;Default B loop index IF.Btn0=1 ;If Fundamental ON, UJ=UI + 1 ;Include extra loop pass ENDIF. UB=UB - U2 ;Next-lower harmonic num IF.QP=1 ;Phase change only on A? UP=0 ;Zero phase here if so ELSE. ;Else 2 = B only, 3 = both UP=Btn3 ;Use Btn3 as-is ENDIF. Ch=3 ;(Top - 1) harmonic stream WHILE.UJ=>0 ;Do total - 1 remaining harms IF.UI=0 ;Last pass (B Fundamental)? UB=1 ;Fund = "1st harmonic" Ch=0 ;Always L.0. channel ENDIF. F=B * UB ;Freq = B fund * harm num IF.Btn0=3 ;If STEP, UF=F * W ;Use max freq as limit ELSE. UF=F ;Else use current freq ENDIF. IF.UF=<SmplRate/2 ;Freq in audible range? Ch.ToneFreq=F ;Set output freq if so Ch.SweepEnd=F * W ;End freq for STEP mode IF.UP=0 ;Zero phase? P=0 ENDIF. IF.UP=1 ;Phase Factor? US=1 - (Buf0 & 1) * 2 ;Alternating top sign Q=Ctrl2 * Buf0 * US ;Top phase = ref US=1 - (UB & 1) * 2 ;Alt harmonic sign P=(Ctrl2 * UB * US - UB / Buf0 * Q) % 360 ENDIF. IF.UP=2 ;Min-Peak? Q=180 * (Buf0 - 1)^2 / UN ;Newman phase P=((180 * (UB - 1)^2 / UN) - UB / Buf0 * Q) % 360 ENDIF. IF.UP=3 ;Random? P=Buf0[UI] % 360 ;Pre-stored rand phase ENDIF. IF.P=<0 ;Neg phase? P=P + 360 ;Pos equivalent ENDIF. Ch.TonePhase=P ;Set output phase Buf0[45 + UI]=P ;Store phase for Mtr Buf0[25 + UI]=UB ;Store harmonic num Ch.Burst=1 ;Burst ON Ch.Level=L ;Set level ELSE. ;Else if freq too high, Ch.Level=0 ;Store for Mtr Buf0[25 + UI]=0 ;Set to silence ENDIF. UB=UB - U2 ;Next-lower harmonic Ch=Ch - 1 ;Next-lower stream UI=UI - 1 ;Next-lower harm index UJ=UJ - 1 ;Next-lower loop index WEND. ;Do all Total-1 harmonics IF.Btn0=0 ;Fundamental OFF? Buf0=0 ;Set phase = 0 ENDIF. UI=4 - Ctrl3 ;Highest unused Left (B) stream WHILE.UI=>0 ;Set remaining to silence Ch=UI Ch.Burst=0 Ch.Level=0 UI=UI-1 WEND. L.0.ToneFreq=B L.0.Level=0 IF.Btn0=1 ;If Fundamental ON, L.0.SweepEnd=B * W ;Set B Fundamental L.0.Level=L ;End for STEP mode L.0.Burst=1 IF.Ctrl3=<4 ;If less than 4 harmonics, R.0.ToneFreq=Ctrl0 ;Set A fundamental also R.0.SweepEnd=Ctrl0 * W R.0.Level=L R.0.Burst=1 ENDIF. ENDIF. ENDIF. ELSE. L.0.ToneFreq=Ctrl0 ;Set fundamental freq L.0.TonePhase=0 ;And phase IF.Btn0=!2 ;If not Fundamental ONLY L.0.Burst=0 ;No Burst L=100 / UN ;100% / total components IF.Btn0=1 ;Fundamental ON? L.0.Level=L ;Set fundamental Level ELSE. L.0.Level=0 ;0 if OFF or SWEEP ENDIF. UI=Ctrl3 - 1 ;Total Harmonics - 1 WHILE.UI=>-1 ;Do all but Fundamental UH=(Btn1+1) * UI + Ctrl1 ;Harmonic number Ch=UI+1 ;Stream number Ch.Burst=0 ;No Burst F=UH * Ctrl0 ;Fundamental * Harmonic IF.Btn0=3 ;SWEEP mode? UF=F * W ;Max freq if so ELSE. UF=F ;Else static freq ENDIF. IF.UF=<SmplRate/2 ;If max freq in range Ch.ToneFreq=F ;Stream (start) freq Ch.SweepEnd=F * W ;Max (for SWEEP) IF.Btn3=0 ;Zero Phases? P=0 ENDIF. IF.Btn3=1 ;Phase Factor? US=1 - ((UI + Ctrl1) & 1) * 2 ;Sign P=Ctrl2 * UH * US ENDIF. IF.Btn3=2 ;Min-Peak Phases? P=(180 * (UH - 1)^2 / UN) % 360 ;Newman factor ENDIF. IF.Btn3=3 ;Random Phases? P=Buf0[UI] ;Pre-computed ENDIF. Buf0[10 + UI + 1]=UH ;Store harmonic num IF.P=<0 ;Neg phase? P=P + 360 ;Equiv. pos ENDIF. Ch.TonePhase=P ;Set stream phase Buf0[30 + UI + 1]=P ;Store for meter Ch.Level=L / UH^Btn2 ;Level EQUAL or 1/N ELSE. ;Max freq out of range Ch.Level=0 ;Prevent aliasing Buf0[10 + UI + 1]=0 ;Don't show it ENDIF. UI=UI - 1 ;Next-lower harm, stream WEND. UI=Ctrl3 + 1 ;Unused upper harmonics WHILE.UI=<8 Ch=UI Ch.Burst=0 ;Set to null Ch.Level=0 Buf0[10 + UI]=0 UI=UI + 1 WEND. ELSE. ;Fundamental ONLY L.0.Level=100 ;Max Level L.0.Burst=0 ;No Burst UI=1 ;Set all harmonics to null WHILE.UI=<8 Ch=UI Ch.Burst=0 Ch.Level=0 Buf0[10 + UI]=0 UI=UI + 1 WEND. ENDIF. ENDIF. UZ=0 ;Force meter update, if active Buf0=0 ;Null crest factor state flag Buf0=0 ;Null A crest factor Buf0=0 ;Null B crest factor Buf0=0 ;Null Continuous crest factor GenUpdate=3 ;Force Generator restart @_Miss_Fund_Mtr ;Do meter update as needed
;<Help=H4913 IF.Btn4=1 ;Show Values? IF.Btn7=1 ;Continuous (not 2-tone) mode? IF.Btn0=3 ;SWEEP mode? UZ=UZ-1 ;Countdown to mtr update IF.UZ=<1 ;Countdown done? S=Posn?D / SmplRate ;Secs since (re)start L=QN * C ;Time for one sweep R=S % L ;Time into current sweep O=R * log2(W) / L ;Octaves into sweep F=2^O * Ctrl0 ;Current sweep freq ENDIF. ELSE. ;Else non-Sweep mode F=Ctrl0 ;Constant freq ENDIF. IF.UZ=<1 ;Countdown done? Mtr0="N" +p6 + "Hz" +p16 + "Deg" ;Show Mtr header U0=Btn0 ;Fundamental button state IF.U0=!2 ;Not Fundamental ONLY? UI=Ctrl3 ;Total harmonics WHILE.UI=>0 ;Show each, count down UH=Buf0[10 + UI] ;Saved harmonic num IF.UH=>0 ;Harmonic present? X=F * UH ;Harmonic freq P=Buf0[30 + UI] ;Saved phase Mtr0=Mtr0 + n + UH + p4 + X + p15 + P ENDIF. UI=UI-1 ;Next-lower harmonic WEND. ;Do all harmonics ENDIF. IF.U0=3 ;SWEEP mode? U0=0 ;Fundamental off if so ENDIF. IF.U0=>0 ;Fundamental on? Mtr0=Mtr0 + n + "1" + p4 + F + p15 + "0.000" ELSE. ;Show in parens if not Mtr0=Mtr0 + n + "1" + p3 _ + "(" + F +")" + p15 + "0.000" ENDIF. IF.Buf0=>0 ;Crest factor ready? Mtr0=Mtr0 +n + " CF " + Buf0 + " dB" ;Show it ENDIF. UZ=10 ;Reset mtr update counter ENDIF. ELSE. ;Show 2-tone IF.(Btn0-3) || !UZ=0 ;STEP mode but not UZ=0 forced? S=Posn?D / SmplRate ;Seconds since (re)start QC=int(S / C) ;2-tone pairs done IF.QC=>UC ;Change since last update? UZ=0 ;Don't repeat UC=QC ;Update for change test L=QN + 1 ;Freq steps, incl start R=UC % L ;Step number in cycle O=2^(R * log2(W) / QN) ;Octave F=O * Ctrl0 ;Current A fund freq E=O * B ;B fundamental freq ELSE. ;Else no change UZ=10 ;Prevent update here ENDIF. ELSE. ;Non-STEP or forced update F=Ctrl0 ;Base A fundamental E=B ;Base B fundamental ENDIF. UG=0 ;Assume no show yet IF.UZ=<1 ;Countdown done? IF.Btn0=<2 ;If so, is Fund OFF or ON? IF.Buf0=>0 ;CF value ready? UG=1 ;Show if so ENDIF. ELSE. ;Else if Fund ONLY or STEP UG=1 ;Always show ENDIF. ENDIF. IF.UG=1 ;Show values now? UZ=10 ;Prevent repeat update Mtr0="N" +p6 + "Hz" +p16 + "Deg" ;Show header IF.Btn0=2 ;Fundamentals ONLY? Mtr0=Mtr0 + n + "1" + QA(A) + p3 + F + p15 _ + "0.000" + n + n + "1" + QB(A) + p3 + E + p15 + "0.000" ELSE. ;Else show harmonics UI=Ctrl3 ;A from top down WHILE.UI=>0 UH=Buf0[20 + UI] ;Saved A harmonic # IF.UH=>0 ;Harmonic present? X=F * UH ;Harmonic freq Mtr0=Mtr0 + n + UH + QA(A) + p4 _ ;Show harm # + X + p15 + Buf0[40 + UI] ;Freq and phase ENDIF. UI=UI-1 ;Next-lower harmonic WEND. ;Do all harmonics U0=0 ;Assume no fundamental IF.Btn0=1 ;Fundamental ON? IF.Ctrl3=<4 ;Less than 4 harms? U0=1 ;Show w/o () ENDIF. ENDIF. IF.U0=1 ;Show fundamental Mtr0=Mtr0 + n + "1" + QA(A) + p4 + F _ + p15 + Buf0 +n ;Incl phase ELSE. ;Fundamental with () Mtr0=Mtr0 + n + "1" + QA(A) + p3 _ + "(" + F +")" + p15 + Buf0 +n ENDIF. IF.Buf0=>0 ;Crest factor A ready? Mtr0=Mtr0 +" CF " + Buf0 + " dB" +n ;Show it ENDIF. UI=Ctrl3 ;B from top down WHILE.UI=>0 UH=Buf0[25 + UI] ;Saved B harmonic # IF.UH=>0 ;Harmonic present? X=E * UH ;Harmonic freq Mtr0=Mtr0 +n + UH + QB(A) + p4 _ ;Show harm # + X + p15 + Buf0[45 + UI] ;Freq and phase ENDIF. UI=UI-1 ;Next-lower harmonic WEND. ;Do all harmonics IF.Btn0=1 ;Fundamental ON? Mtr0=Mtr0 + n + "1" + QB(A) + p4 _ ;Show it + E + p15 + Buf0 ;Incl phase ELSE. ;Else show fund in () Mtr0=Mtr0 + n + "1" + QB(A) + p3 _ + "(" + E +")" + p15 + Buf0 ENDIF. IF.Buf0=>0 ;Crest factor B ready? Mtr0=Mtr0 +n + " CF " + Buf0 + " dB" ;Show it ENDIF. ENDIF. ENDIF. ENDIF. ENDIF.
;<Help=H4913 IF.Buf0=<2 ;Waiting for crest factor update? IF.Btn0=<2 ;Only for Fund OFF or ON IF.Btn7=1 ;Continuous Tone? UT=SmplRate / Ctrl0 ;Fundamental period @_Miss_Fund_CF_Core ;Compute CF Buf0=V ;Store Cont CF Buf0=3 ;Status = Cont CF done UZ=0 ;Force _Mtr update @_Miss_Fund_Mtr ELSE. ;Else Two-Tone S=Posn?D / SmplRate ;Seconds since (re)start Q=S % C ;Secs into this cycle IF.Buf0=0 ;Waiting for A CF? IF.Q=>R ;Done with A Rise? IF.Q=<R + H - 1024 / SmplRate ;Before A High end? UT=SmplRate / Ctrl0 ;Fund A period @_Miss_Fund_CF_Core ;Get CF Buf0=V ;Store A CF Buf0=1 ;Status = A CF done UZ=0 ;Force _Mtr update @_Miss_Fund_Mtr ENDIF. ENDIF. ELSE. ;Else waiting for B CF IF.Q=>R+H+R+G+R ;Done with B Rise? IF.Q=<R+H+R+G+R+H - 1024/SmplRate ;Before B High end? UT=SmplRate / Buf0 ;Fund B period @_Miss_Fund_CF_Core ;Get CF Buf0=V ;Store B CF Buf0=2 ;Status = B CF done UZ=0 ;Force _Mtr update @_Miss_Fund_Mtr ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. ENDIF.
;<Help=H4913 IF.Btn6=0 ;Only for waveform display Uc=Ch ;Save current channel during task Ch=1 ;Set to 1 for BwSig on Buf1 Buf1="<=W2" ;Copy Left Out waveform to Buf1 V=BwSig(0,UT) ;Get RMS over period UT UQ=Buf1?p ;Pos peak QQ=abs(Buf1?n) ;Abs of neg peak IF.QQ=>UQ ;Neg larger? UQ=QQ ;UQ = largest ENDIF. V=20 * log10(UQ/V) ;Peak/RMS ratio, as dB Ch=Uc ;Restore channel before task exit ELSE. V=0 ;No value if not waveform display ENDIF.
Questions? Comments? Contact us!We respond to ALL inquiries, typically within 24 hrs.
Over 30 Years of Innovative Instrumentation
© Copyright 2007 - 2017 by Interstellar Research
All rights reserved