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
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.

Dani AI

Generated

Nice catch by — the real bug was reopening the output file inside the loop. Opening a WAV for writing truncates/rewrites the header, so every iteration you were effectively starting from scratch. @alwasLearning was right: open the final file once, stream all inputs into it, then close it.

A few practical points and safer patterns that solve edge cases:

  • Clarify terms: "concatenation" = append files end‑to‑end; "mixing" = overlay/sum samples (different algorithm and clipping concerns).
  • For concatenation, copy the sample rate, channel count and format from the first input into the SF_INFO used to open the output. Refuse or resample if later inputs differ.
  • Allocate your read buffer as (blockFrames * channels) floats — sf_readf_float and sf_writef_float work in frames (not raw samples). Check return values for errors and for zero (EOF). Use automatic containers (std::vector<float>) instead of malloc/new to avoid leaks. Use std::to_string or snprintf to build filenames safely.
  • For mixing/overlay: stream all tracks and sum their samples into an output buffer, apply a gain or divide by the number of contributors to avoid clipping, or run a normalization/limiter afterwards. If inputs have different sample rates, use a resampler (libsamplerate or soxr) — libsndfile does not resample for you.

Minimal workflow (conceptual):

// pseudocode outline (not the forum's original code)
open first input -> read its sfinfo -> set out_sfinfo to match -> open output once
for each input file:
  open input
  while ((frames = sf_readf_float(in, buf.data(), blockFrames)) > 0)
    sf_writef_float(out, buf.data(), frames)
  close input
close output  // important: libsndfile writes final header here

Always check sf_open return values and sf_strerror for diagnostics. Following these patterns will make the loop robust and avoid truncation, buffer mis-sizing, and format mismatches.

OK, problem solved with help of user alwasLearning from go4expert.com.
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:

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...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.