libsndfile-mixing any number of soundfiles in loop

lason.naitsirk's Avatar, Join Date: Apr 2009
Newbie Member
Hi,
I am very new in programming (six months), so many apologies for silly questions.
I intended to write a console prog that uses libsndfile. It is kind of synthetiser. It reads text file created by user, where on each line, the information about parametres of sound synthesis are stored (frequency, amplitude, FM, AM, Additive, envelopes, effects...). For each line there is an corresponding process loop, that counts and performs synthesis and in the end creates *.wav soundfile. So in the end of main loop there are as many soundfiles as number of lines in the text file. These sound files may differ in lenth, but not in number of channels and samplerate, there are given names by the number of line in text file, that represents their data (i.e.: 0.wav, 1.wav, 2.wav – for textfile of three lines). This works perfectly...everythink is created and closed, there are no warnings during compilation, console does not fail. – But now should come the easy stuf. I need to mix all the files into one final output file. I want to create an loop taking these temporary files and writing them into the output file in line (witing one after another to the end of output file). I have tryed to do this in several ways, but I am probably not using the sf_seek function correctly, as the files are just rewriting themself...or there is somethink bad with my way of memory managemant. Please can you support me with any idea, what I am doing wrong? Or better, write an example code how to write one *.wav file to the end of another? I am very fresh in c++.
Thank you very much!!!
this the relevant part of my code:
...closing of predecesing part of code
|
v
Code:
for(int i=0; i<n; i++)
{   
	char b[10];
	itoa(i, b, 10 );
	char NAMEIN[8] = {b[0], '.', 'w', 'a', 'v'};
 psfinfoin = (SF_INFO *) malloc(sizeof(SF_INFO));
	psfinfoout = (SF_INFO *) malloc(sizeof(SF_INFO));
 if(!(psfin = soundin_open(NAMEIN, chans, sr))){ cout << "error opening output file\n" << NAMEIN << endl; exit(-1);}
	else cout << "soubor " << NAMEIN << " uspesne otevren pro cteni" << endl;
		
	buffer1= new float [def_len];
 if(!(psfout = soundout_open("out.wav"))){ cout << "error opening output file\n" << endl; exit(-1);}
	else cout << "soubor <out.wav> otevren pro psani" << endl;
	do {
		sf_seek(psfout, 0, SEEK_END);
		count1 = sf_readf_float(psfin, buffer1, def_len);
		sf_writef_float(psfout, buffer1, count1);
		}
	while(count1);
	soundin_close(psfin);
	soundout_close(psfout);
	free(psfinfoin);
	free(psfinfoout);
	free(buffer1);
}
|
v
than delete all temporary files...and end the code
_________________________________________
I know that I am mixing C with C++, but seems to me, that it is not the problem.
Integer n in for loop is the number of files plus 1. <def_len> in the code has value of 1024.
p.s.: sorry for my English, still learning
Thank you,
K.

Last edited by shabbir; 1Apr2009 at 18:58.. Reason: Code blocks
0
alwaysLearning's Avatar, Join Date: Mar 2009
Go4Expert Member
Hi,

First of all, i will only suggest several thing which you can do, trial and error basis.

By looking at your code, soundout_open, i dont know in what mode this function opening the output file. To open a output file there are several mode, in your case it will be append.

So mostprobably its opening that file only in write mode, which actually re-write the entire file.

First thing i will try, is take that function out of the first loop and call only once.

Code:
if(!(psfout = soundout_open("out.wav"))){ cout << "error opening output file\n" << endl; exit(-1);}
	else cout << "soubor <out.wav> otevren pro psani" << endl;

for(int i=0; i<n; i++){

   /*Open input file one by one and write to that output file*/


}
second thing i might try ( if the last one doesnt solve the issue ) is i wont use f_seek as, you are not closting file in the loop. I would do something like this:
Code:
           do {
		count1 = sf_readf_float(psfin, buffer1, def_len);
                                 
                                if(count1 <= 0)
                                      break;
		sf_writef_float(psfout, buffer1, count1);
                                psfout += count;
		}
	while(1);
last thing is: I was looking at the library functions you are using and i didnt find the function you are using to open the sound files.

I found this one:
SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ;

You may use this one with proper mode, but i am in doubt whether its solve your issue.
0
alwaysLearning's Avatar, Join Date: Mar 2009
Go4Expert Member
Code:
if(!(psfout = soundout_open("out.wav"))){ cout << "error opening output file\n" << endl; exit(-1);}
	else cout << "soubor <out.wav> otevren pro psani" << endl;

for(int i=0; i<n; i++){

   /*Open input file one by one and write to that output file*/


}

/*Close the output file here, not in the for loop */
0
lason.naitsirk's Avatar, Join Date: Apr 2009
Newbie Member
Hi,

thanks a lot for quick response.
Yes, you are right, the proper way of opening files is quite different, from what you can find in that code, Victor Lazzarini, has succesfully rewritten the files to make them more simple in use.
This is the function prototype, that you could not find:

SNDFILE *soundin_open(char* name, int chans, float sr){
SF_INFO info;
SNDFILE *sf = sf_open(name, SFM_READ, &info);
*sr = (float) info.samplerate;
*chans = info.channels;
return sf;
}

I am sorry, that I did not write it before.
Your code seems to be very interesting to me, but I do not understand one thing in it.
how you know, or determine, the size of psfout in that do loop? it is pointer, isn't it?
I can not compile such a solution, because of the error:
error C2036: 'SNDFILE *' : unknown size
I think this is related to the psfout...

do
{
count1 = sf_readf_float(psfin, buffer1, 1024);
if(count1 <= 0)
break;
sf_writef_float(psfout, buffer1, count1);
psfout += count1;
}
while(1);

thank you very much...
0
alwaysLearning's Avatar, Join Date: Mar 2009
Go4Expert Member
Did you take out the function soundout_open as i mentioned before?

and also dont use this: psfout += count1;
Code:
   do {
		count1 = sf_readf_float(psfin, buffer1, def_len);
                                 
                                if(count1 <= 0)
                                      break;
		sf_writef_float(psfout, buffer1, count1);
                               
                                 /* psfout += count1; */  
                              
		}
	while(1);
file pointer should automically be advanced as you read.

usually in a pointer, if you add a number with the pointer, it means your address is increased by that number ( depends on the size of the data to which pointer points) . Forget these and go ahead with the above.
0
lason.naitsirk's Avatar, Join Date: Apr 2009
Newbie Member
OK!!!
Thanks a lot!!!
The trick was really in opening the output one time only and closing it after the loop...I am so stupid...no the bit of code is like this:
Code:
if(!(psfout = soundout_open("out.wav")))
{
cout << "error opening output file\n" << endl; exit(-1);
}
    else cout << "file <out.wav> opened for writing" << endl;

for(int inte=0; inte<nn; inte++)
{
    char b[1];
    itoa(inte, b, 10 );
    char NAMEIN[8] = {b[0], 'i', 'n', '.', 'w', 'a', 'v'};

    buffer1= new float [def_len];

    if(!(psfin = soundin_open(NAMEIN, chans, sr)))
{
cout << "error opening output file\n" << NAMEIN << endl; exit(-1);
}
    else cout << "soubor " << NAMEIN << " uspesne otevren pro cteni" << endl;
    do {
        //sf_seek(psfout, 0, SEEK_END);
        count1 = sf_readf_float(psfin, buffer1, 1024);
        sf_writef_float(psfout, buffer1, count1);
        }
   while(count1);
   soundin_close(psfin);
   free(psfinfoin);
   free(buffer1);
}
    soundout_close(psfout);
    free(psfinfoout);
.
.
.
continue...

ad it works!!!
Great.

This was really helpfull...I owe you a big bottle of champaign (or something else)...any time you are in Czech Republic... k.nosal@email.cz

all the best

k

Last edited by shabbir; 1Apr2009 at 21:05.. Reason: Code block