-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Different input frequencies are getting played as the same output frequency #3
Comments
@jhale1805 I think you hit the nail on the head when you said "I'm wondering if this has something to do with how this package focuses on playing specific notes (i.e. music composition)?" I never did any sort of detailed testing of specific frequencies, like you are doing now. This module was very much intended for producing musical tones, and the extent of my testing was pretty much just using my ears to make sure things sound musically OK. That being said, I will take a look at the code which handles specific frequency values, and see if there is an obvious problem that could cause such a loss of precision. Thanks! |
@jhale1805 I can possibly help speed up your investigation; the problem is most likely with the _sine_wave_table function here https://github.com/eriknyquist/tones/blob/master/tones/tone.py#L6 This function is called by the Tone.samples() function (right here https://github.com/eriknyquist/tones/blob/master/tones/tone.py#L197), to obtain a set of samples that make up a single 360 degree sine wave oscillation in the desired frequency/sample rate/amplitude (that is, a single period's worth of samples of the output sine wave waveform). The Tone.samples() function then iterates over this table multiple times, as many times as is needed to create the number of samples we need for the requested note time. My guess is that there is some significant loss of precision that occurs when I do I'm not sure exactly how I would resolve that, right now, but this is the area I'm drawn to right now based on your description. |
OK, so after I explained that to you I'm thinking that the problem is indeed This approach assumes that the full period of any sine wave at any frequency can be described by a discrete number of samples, when in reality, the full period of a sine wave is likely going to have some "fractional" sample at the end (e.g. a full period of 1555Hz, at 44100 sample rate, works out to 28.36 samples), unless the sine wave frequency happens to be an exact multiple of the sample rate. This might also explain the weird harmonics reported in #1, since the issue I described above would result in sine waves that are not perfect-- there would be little "blips" in the waveform between every period, which I'm guessing would result in some odd harmonic content. I think the correct way to do this would be to generate all samples for the full note length at once, instead of just doing a single period and then duplicating it, just like is being done in this stackoverflow answer; https://stackoverflow.com/questions/8299303/generating-sine-wave-sound-in-python I don't have time to work on it and test it right now (I can get to that next weekend), but I thought I would just dump that info here in case it helps you out. |
I think you're on to something. I plotted the output waveform using this Stack Overflow post as a guide (https://stackoverflow.com/a/18625294) and got the following output (zoomed in a lot). Just as you predicted, there is an odd change of slope at the end of each period that I don't think can be attributed to the minor imperfections introduced by using digital samples instead of an analog signal. In this example, it looks like the slope notably decreases at the end of each period, which would result in a slightly lower output frequency. This seems to illustrate how, as you eloquently said it, some input frequencies "snap" to the same output frequency. I'll try out the solution you found and give another update in a bit. Just for reference, the exact code that produced that image
|
Fixes eriknyquist#3 Resolved the issue where some input sine frequencies were processed into the same output frequency. No work/testing was done to see how this change affected other waveforms.
In #2 I referenced a bug I was investigating. Here it is.
Background
I'm trying to use this library to prototype a personal data over sound project. I'm working on using the presence of a sound at any of 24 different frequencies to convey the data my application needs. Eventually I will be using several of these frequencies in parallel, which maps really well to this package's support of different tracks.
Issue
The issue I'm finding is that when I use this package to play a test sound at each of my chosen 24 frequencies I notice that some of the higher frequencies get played as the same tone.
Low Frequency Example
Here's the code:
And here's a spectrogram of the frequencies I'm getting as a result:
![Screenshot_20201124-181026_smaller](https://user-images.githubusercontent.com/47901316/100170403-d212b680-2e82-11eb-9c5d-a4038658e025.png)
High Frequency Example
It appears as though playing higher frequencies exacerbates the problem. This code plays the same frequency intervals (not note intervals) but starting 3000 Hz higher than the previous example.
Here's the resulting spectrogram.
![Screenshot_20201124-183135](https://user-images.githubusercontent.com/47901316/100170802-af34d200-2e83-11eb-94da-2ea33beeb390.png)
Other Thoughts
I'm wondering if this has something to do with how this package focuses on playing specific notes (i.e. music composition). Perhaps my frequencies are simply getting rounded to the closest note? I didn't see anything that would seem to be doing that in the
mixer.add_tone()
function, but it's an idea that I've had nagging at me while I look through things.I'm happy to help develop a solution to improve this great package, I'm just getting stuck when I tackle it on my own. Hoping @eriknyquist has some added insight into why this might be occurring.
The text was updated successfully, but these errors were encountered: