How to Read and Write Wav Files

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

i'm sorry i meant to say the code posted from the thread starter's tutorial page. yeah there were questions that i wanted to ask about the code before i compiled it after looking through it but i didn't cause i thought it was just something you could overlook(the different chunks not of the wavefile "seeming"(from a newbs point of veiw) to not be implemented).

-edit-
and i was just trying to do what the tutorial sets out to do. read and write a wav file. i figured that once i got that working, then i'd start tearing it apart and putting new things together.

Post

PaulMorel wrote:This article is supposed to be a "How-To", not a programming practices article.

Yes, I left out a lot of the intricacies of the format. The article is supposed to give people a practical introduction to WAV IO, not school them in format minutiae. The truth is, it's aimed more at musicians who want to be programmers than at programmers who are also musicians.

I DID leave out almost ALL data checks. I never really confirm that the data is good at all. I also left out anything having to do with endian-ness, and I even left in some classic code vulnerabilities. I didn't want to confuse the audience with details that they didn't absolutely need. I wanted to get them started.

Anyway, I updated the article to make this more explicit. Thanks for the feedback, but please keep in mind that the article is an introduction, not a textbook. :wink: I understand that it won't help you pros.
ok i've read about the spec in more places than one, where do i go to learn after i've gotten started?

Post

read my code :hihi:

you can find a lot of useful information via google as well, although it is hard to pick out those bits, 1 in 100 where the other 99 are useless.

you can ask me any questions that you have, and there are others on this board of course. as for the spec itself, if you're really wanting to be accurate you might want to get an official copy.. i'm not sure where you'd do that since as far as i know nobody does that. unless you really need extra functionality, the stuff implemented in my code should be great.

(read page #2 in this thread...)

Post

hehe cool thanks :) i'll do that. i think i need a notepad and take notes of the structure of everything. maybe that would help me understand things better. yay a new use for the notepad i bought.

Post

aciddose wrote:

Code: Select all

template<class T, class FT>
T hermite(const T &A, const T &B, const T &C, const T &D, const FT &X)
{
 T E = (((B - C) * (FT)3.0 - A) + D) * (FT)0.5;
 T F = ((C * (FT)2.0) + A) - ((((B * (FT)4.0) + B) + D) * (FT)0.5);
 T G = (C - A) * (FT)0.5;
 return B + (((E * X) + F) * X + G) * X;
} 
Hi aciddose,

OUCH! That is some harsh code - Am I just being picky or are the constants just a tad too anonymous (A, B, C, D, X)?
How is anyone able to decifre what you just wrote when you don't explain at least what the variables in play are?

I'm not even gonna comment on the other template helpers in the second code block... :help:

Don't get me wrong - you are helping greatly and it is really appreciated, but when you look at code like this I don't blame anyone for saying that the learning curve is extremely steep!

But still thank you - it IS appreciated.
ooO Off to look up the hermite and others - there must be references to them as design patterns or something.. :o

/Dennis P

Post

hermite is a type of spline, which is a linear matrix transformation applied to vectors constructed from sampled points A,B,C,D.

A = s[-1]
B = s[0]
C = s[1]
D = s[2]

so you want to pass these to the function in that manner,
hermite<float>(myfloats[index-1], myfloats[index], myfloats[index+1], myfloats[index+2], fraction);

the purpose of a spline is to approximate the value of the sample at [index + fraction] based upon the values two samples before and two after that mid-point.

linear interpolation, also called 'lerp' is used to do the same thing, but only using two samples rather than four, and by merely drawing a straight line between those two samples.

i cant really explain this any further than i have at this point unless you want to learn a whole lot about vectors, linear algebra and so on. here is a bad, yet simple way to look at it: the calculations find vectors in three dimensions based upon those four sample points, and they are then put into a matrix which is multiplied with the vector formed by simply those four samples V(A,B,C,D) * M(lots of constants in 4x4 matrix), and the normal is taken and used directly as our output sample.

basically, the hermite function i've given you is a much simplified version of the whole function using matrices. we've taken all the equations out of the matrix and applied them directly, eliminating any ones or zeros and redundant calculations.

reading up about splines/cubic/hermite/etc on wikipedia is a great idea.

Post

aciddose wrote:hermite is a type of spline, which is a linear matrix transformation applied to vectors constructed from sampled points A,B,C,D.

A = s[-1]
B = s[0]
C = s[1]
D = s[2]

so you want to pass these to the function in that manner,
hermite<float>(myfloats[index-1], myfloats[index], myfloats[index+1], myfloats[index+2], fraction);
Thank you aciddose,

This was exactly what I needed to know how to proceed in the right (or left? :hihi: ) direction :!:

And by knowing that the template is actually a "practically best guess" and by knowing what to feed into it, the template actually makes a lot more sense 8)

So thank you very much for providing this info!
/Dennis P

Post

thanks to who ever provided the riff.h/cpp classes.

i've managed to extend them and get my little sampler working. now to start writing pitch shifting and add a GUI.

Post

hey there aciddose,
I was gonna just PM you, but for some reason that i might sooner or later find rediculous, i've decided to post it in the thread. Hey, maybe someone will learn from it :)

As i continue my life-long quest to load a (frikkin)wavefile, i've decided to give your code a deeper look and pick your brain a bit(no disrespect to the thread starter, PaulMorel. you're code and tutorial was greatly appreciated :) ) I don't understand all of it but i figured that i could only do further examination of it through trial and error with experimentation.

I'm trying to use the LoadRIFFWAVE() function from main(). I've tried all kinds of things, one or two methods actually got the program to load, but i got this runtime error that says that the char* filename argument isn't initialized. here's a code snippet (yeah, i know you were waiting for that :) )

Code: Select all

// Aciddose ADRIFF.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include "c:\Documents and Settings\esiadmin\My Documents\source\aciddose\riff.h"


int main(int argc, char* argv[])
{
	/*ADRIFF::PCM* wtf;
	char* omfgFile = &ADRIFF::LoadRIFFWAVE;*/

	if( argc != 2 )
	{
		std::cout << "Please specify a filename and directory." << std::endl;
	}
	else
	{
		std::cout << "Ok gonna load a .wav file in this bitz." << std::endl;
		if(ADRIFF::LoadRIFFWAVE(&pcm, &filename)/*ADRIFF::LoadRIFFWAVE(ADRIFF::PCM *pcm, char *filename)*/)
		{
			std::cout << "File loaded in this mofo!\n" << std::endl;
		}
	}

	return 0;
}
hmm.. i got a stupid error with that one. i'll leave it as an example of things i've been trying and rewrite the code to the way i had it when it ran.

Code: Select all

// Aciddose ADRIFF.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include "c:\Documents and Settings\esiadmin\My Documents\source\aciddose\riff.h"


int main(int argc, char* argv[])
{
	ADRIFF::PCM* wtf;
	char* omfgFile;

	if( argc != 2 )
	{
		std::cout << "Please specify a filename and directory." << std::endl;
	}
	else
	{
		std::cout << "Ok gonna load a .wav file in this bitz." << std::endl;
		if(ADRIFF::LoadRIFFWAVE(wtf, omfgFile)/*ADRIFF::LoadRIFFWAVE(ADRIFF::PCM *pcm, char *filename)*/)
		{
			std::cout << "File loaded in this mofo!\n" << std::endl;
		}
	}

	return 0;
}
ok that's what i did. and when i run it, with with an argument like ADRIFF "C:\loadmydamn.wav" it get the error i mentioned earlier. Image

P.S.
I am looking at a few different books right now, trying to find some info on pointers and functions. but nothing i've found so far is helping much. i'll keep searching.

Post

You never set the omfgFile. You just declare it. It never gets a value. My pointer-fu is a bit weak but either omfgFile = argv; or omfgFile = argv[0];
should work i think. Don't feel like firing up MSVC for the moment. Dinner is cooking. :)

EDIT: Silly me. argv[0] is the name of the program. argv[1] it should be(i think);

OK. You got me firing up MSVC. :)

EDIT2: Yep. char* omfgFile=argv[1]; did the trick.
BTW which version of MSVC are you running ? I had to fix lots of stuff before it compiled. Could just be me sucking though. :hihi:
EDIT3: You never initialize the ADRIFF::PCM* pointer either.
ADRIFF::PCM* wtf = new ADRIFF::PCM();
should do the trick.

It works here now.

Post

sweet!! thanks!! omg that's tricky stuff.... maybe i should go back to the very beginning of pointers and classes. omfg that's gonna suck. but i guess it must be done!!!
i'm running MSVC 2005 standard edition.

-edit-
ahh so you're the guy with the clever quote in their sig that's been getting me girls at the sophisticated parties!! i was wondering when i'd bump into that sig again :hihi:

Post

laserbeak wrote:omg that's tricky stuff....:
It's really easy stuff actually. Imagine the following:

Code: Select all

int a;
int b;
int c = a + b;
That won't work because a and b don't yet have any value. You have to assign a value to them before you use them. Same thing with char pointers and objects. By doing this:

Code: Select all

ADRIFF::PCM* wtf; 
char* omfgFile;
you're just telling the compiler "I'm going to use this stuff later on,just so you know" but you never set the value.

Take the char pointer *omfgFile for example,how is it to know that it should take the value of the second argument in argv unless you tell it ?

BTW if you type "laserbeaksMarvelousWavLoadingProgram Sine.wav" in the console argv[0]= "laserbeaksMarvelousWavLoadingProgram" and argv[1]="Sine.wav" and should you add more arguments they obviously become argv[2],argv[3] and so on.

Same thing with the wtf pointer. That is a pointer to an object so it needs to be initialized with a call to the constructor. wtf = new ADRIFF::PCM();

Simple stuff really. Wait 'til you get to heavy pointer arithmetic stuff. Enough to make a grown man cry. :cry: :D
ahh so you're the guy with the clever quote in their sig that's been getting me girls at the sophisticated parties!! i was wondering when i'd bump into that sig again
I'm glad i can be of service on so many levels. I'm useful in so many ways it's almost scary. :D

Post

hmm i see. i was thinking more along the lines of "i've made a pointer, here take it, damnit!!"

anyway, buddy of mines hooked me up with a series of C programming videos in .mov format and it has an extensive pointer section. i'm gonna look at this over the weekend

Post

accidose:
is this code for a basic format? it looks like it checks for a wavefile to me, but when i run it, i always get a return value of -1. i'm gonna print all the info and see if it matches a wavefile. is there any advice you could give me?

-edit-
nvm.
turns out it was my file directory syntax. :x

Post


Post Reply

Return to “DSP and Plugin Development”