Best way to incorporate wav audio into a module?

In some cases, but not in this case. Once you have digital nasties in your signal it is generally impossible to get rid of them. They are going to be in-between frequencies that are supposed to be there, and there is no practical way to filter them out.

The issue here is that if the user sets a sample rate that isn’t the one the samples were recorded at, they will play at the wrong speed. So usually you want to do something to prevent that. And to do that you need to make up in-between samples if you are going up, or throw some away if you are going down.

So just getting the speed-pitch right takes some trickiness.

And you “can’t” really just repeat samples or drop some. It can sound awful. It’s not really aliasing, I don’t think. It’s usually called “interpolation noise”, I think.

Wavetable VCOs have to deal with this, since they are supposed to play at the right pitch and sound ok, and have to be transposed all over the place. That said, afaik they all play back at the correct pitch, but some do actually just drop or repeat samples.

But a good one, like the VCV WT VCO will have some fancy interpolation so that it sounds good when transposing. You might look at that that does. But beware, this is a pretty complex topic, and pretty quicky ppl start to talk about polyphase filters, sinc resamplers, etc…

I would say approachable solutions are to either let it sound bad, or find an implementation you can borrow (like the VCV one)

1 Like

Correctly you have to apply cubic interpolation between samples. In the example code, the float-value step_amount is truncated to the int-value sample_position. You have to prevent this loss of data and calculate the sample-data in between the 2 samples accordingly to the position after the decimal point of the float-value. The Cattmul-Rom algorithm should give you good results.

If you’re downsampling, you should apply a low-pass-filter operating under the Nyquist-frequency of your sample before you do the interpolation.

But before all that: Make it run!

1 Like

That is far from true. a) you don’t “have” to do anything, and b) cubic interpolation is not a perfect solution to this problem, nor is it the only one.

That said, I have always used cubic interpolation because it’s relatively easy, and it sounds “good enough” to me. Others are more finicky, and will so something fancier. As I mentioned before, some do something worse.

NYSTHI Seven seas is an interesting example. I think it has three different uses selectable qualities for this. Presumably so you can trade off CPU usage for sound quality.

2 Likes

Yes, you’re right. No one “has” to …

Yes, it’s a trade off between CPU usage for sound quality.

Thank you for your wise point of view. :+1:

maybe more “nick picky” that wise :wink: but thanks. Your advice was of course quite good.

Sidenote: Ideally, the better way to do this is to create a global array, and use compile-time code execution to read audio file and pre-fill the array. This is possible in some newer languages, but not in C++ AFAIK. Converting large binary data to text and have the C++ compiler parse it back is not fast.

Another dangerous hacky way is to modify the executable binary (you probably should not do this):

1 Like

what on earth are you talking about, and b) do you write VCV modules?

  1. It means to execute arbitrary code before the program is compiled. You can use this to pre-compute look up tables, control compilation, write global data (what OP needs), or communicate to Mars rover for your executable name. If you do have time and want more information, see Jonathan Blow - Demo: Base language, compile-time execution.

  2. Yes, I’ve wrote some modules. The code sample here is for easy demonstration.

1 Like

I think he refers to this:

2 Likes

Not quite this definition, the code being run here can be non-pure functions (or procedures), therefore it can read/write files, run shell commands, modify global states, etc.

Yes, by making it possible to integrate and automate everything into the build-process, it makes it much easier to swap data files. But keep in mind, the OP is a coding newbie.

1 Like

Wow! Thanks so much Bruce for that detailed and thoughtful explanation. You raise a lot of good issues to be aware of, and even though a lot of “putting it to practice” goes over my head, I do get the theory behind it all.

Also, thank you for suggesting I look at the VCV WTVCO as an example. I think my best course for now, is to continue getting something up and running, which with the help of @clone45 I got a really good jumping off point, and my starting point.

Having the samples unintentionally pitched up or down due to the user using other sample rates, is something I’d want to avoid at the very least. So again, I appreciate the wealth of knowledge shared in this thread, as I’ve not only learned so much, but also have been given a lot to consider :slight_smile:

1 Like

Wow! Thanks for this, I will definitely check this out. You’ve given me a lot to consider here. :slight_smile:

Thank you for chiming in @Letheward, I will give this a look. Might be over my head at this point, but we all start somewhere. Who knows, it could be useful at some point down the line. So thank you again :slight_smile:

This is true, especially when it comes to coding for this platform. It would be ignorant of me to dismiss any information provided by the wealth of knowledge in this community. We all start somewhere, and we all have our own process.

I’ll put this here, since you asked about dealing with aliasing by filtering the output, and Bruce said that once you have introduced nasties, its pretty much impossible to get rid of them.

The reasons why this is true are not easy to appreciate, until you get to grips with dsp. So i thought it might be worth my trying to give a simplistic explanation.

The cause of the nasties is parts of the signal above the nyquist frequency. But what that causes are aliases, and they lie below the nyquist frequency. They are pretty much impossible to remove or filter out, precisely because they are in amongst the frequencies that you want to keep, mixed in with them, but out of tune with your intended sounds.

3 Likes

Are they in the library? I don’t see a brand called “Letheward” there.

Nepeta: 3 simple but weird modules

Not yet, they are a few simple experiments, and are not optimized and extensively tested, so I think the package do not have enough value to ship to general users. I may submit to the library when I get 5 or 6 modules.

1 Like

For the actual solutions, other people in this thread have summarized them very well.

It’s just a reminder that there is a simpler, faster, and much powerful way to do this, but unfortunately not in C++ now.

The hacky way (modifying the executable) is something you should not do. It’s a showcase that it’s still possible to directly fill global data without compile-time execution, although this is out of the programming language’s range and is very dangerous.

2 Likes

Thank you for this. I understood most of this stuff from an end users point of view, before taking a crack at this. So it’s really good to know more about what’s happening on the back end here. Aliasing might just be part of the character after all, now that I got something up and running, and thinking about where I’m going with this. For other kinds of modules using audio, I get that it’s important to avoid it.

But thank you again! I apologize about not responding to you sooner :slight_smile:

1 Like