How to save WAV file from buffer?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

How to save WAV file from buffer?

Dan Mistrenko
Hello Fre;D

Help me please!
I work with digital sound processing on Lazarus because
I have old units written on Pascal and Object Pascal.
Now I need open WAV file then take buffer from it and process this buffer.
Then I need save in new WAV file that has processed buffer.
But I can not save the buffer in WAV file with parameters of opened file.
Specifically I have such parameters in open WAV file

thebufferinfos.SampleRate = 44100
thebufferinfos.SampleRateRoot = 44100
thebufferinfos.SampleFormat = 0
thebufferinfos.Channels = 1
thebufferinfos.Genre   = 0
thebufferinfos.HDFormat = 65538
thebufferinfos.Sections = 1
thebufferinfos.Encoding = -1
thebufferinfos.bitrate = -1
thebufferinfos.Length   = 61911
thebufferinfos.LibOpen = 0
thebufferinfos.Ratio   = 2

but I can not set this parameters for the file I like to save. When I perform the route

  PlayerIndex1 := 0;
  uos_CreatePlayer(PlayerIndex1);
  InputIndex1 := uos_AddFromMemoryBuffer(PlayerIndex1,thebuffer,thebufferinfos, -1, -1);
  if InputIndex1 > -1 then
  begin
      uos_EndProc(PlayerIndex1, @ClosePlayer);
      OutputIndex1 := uos_addIntoFileFromMem(PlayerIndex1, Pchar('/home/user/MyWav.wav'),-1,1,-1,-1,1 );
      if OutputIndex1 > -1 then
      begin
        uos_Play(PlayerIndex1);
      end;
  end;

I get WAV file with such parameters

thebufferinfos.SampleRate = 44100
thebufferinfos.SampleRateRoot = 44100
thebufferinfos.SampleFormat = 0
thebufferinfos.Channels = 1
thebufferinfos.Genre   = 0
thebufferinfos.HDFormat = 65538
thebufferinfos.Sections = 1
thebufferinfos.Encoding = -1
thebufferinfos.bitrate = -1
thebufferinfos.Length   = 30955
thebufferinfos.LibOpen = 0
thebufferinfos.Ratio   = 2

What do I do wrong?

Thanks for an answer.
Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
Hello.

AddintofileFromMem() is used for memory streams (<> memory buffer).

Using Addintofile() does not work for you ?):

PlayerIndex1 := 0;
  uos_CreatePlayer(PlayerIndex1);
  InputIndex1 := uos_AddFromMemoryBuffer(PlayerIndex1,thebuffer,thebufferinfos, -1, -1);
  if InputIndex1 > -1 then
  begin
      uos_EndProc(PlayerIndex1, @ClosePlayer);
      OutputIndex1 := uos_addIntoFile(PlayerIndex1, Pchar('/home/user/MyWav.wav') ); // here change
      if OutputIndex1 > -1 then
      begin
        uos_Play(PlayerIndex1);
      end;
  end;

function uos_AddIntoFile(PlayerIndex: cint32; Filename: PChar): cint32;
// Add a Output into audio wav file with Default parameters
// PlayerIndex : Index of a existing Player
// FileName : filename of saved audio wav file

function uos_AddIntoFile(PlayerIndex: cint32; Filename: PChar; SampleRate: cint32;
  Channels: cint32; SampleFormat: cint32 ; FramesCount: cint32 ; FileFormat: cint32): cint32;
// Add a Output into audio wav file with custom parameters
// PlayerIndex : Index of a existing Player
// FileName : filename of saved audio wav file
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (1:mono, 2:stereo, ...)
// SampleFormat : default : -1 (2:Int16) (1:Int32, 2:Int16)
// FramesCount : default : -1 (= 65536)
// FileFormat : default : -1 (wav) (0:wav, 1:pcm, 2:custom);
//  result :Output Index in array  -1 = error

Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
Re-hello.

Maybe you will need to use Addintofile(...) with custom parameters, according your buffer setup.

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
Re-re hello.

I see that you are using for the buffer:
thebufferinfos.SampleFormat = 0 (float resolution)

Wav file format usually uses integer (thebufferinfos.SampleFormat := 2 (or 1);

I did not test but maybe others applications can read wav files with float samples.

I fear that you will need to explore with different resolutions to get what you want.

Fre;D

Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

Dan Mistrenko
Re-hello Fre;D!

Thanks for the answer.
I use thebufferinfos.SampleFormat = 0 because
I get real value when I have opened wav file with this parameter.
I open wav file with that time dependence (wav file opened in Audacity)



by the next route

  Res := uos_LoadLib(Pchar(PA_FileName), Pchar(SF_FileName), pchar(MP_FileName), nil, nil, nil) ;
  If Res=0 Then
    thebuffer := uos_File2Buffer(pchar(SoundFilename), 0, thebufferinfos, -1, -1);

I get the next time dependence of sound sygnal



But if I save that buffer in wav file by route

PlayerIndex1 := 0;
  uos_CreatePlayer(PlayerIndex1);
  InputIndex1 := uos_AddFromMemoryBuffer(PlayerIndex1,thebuffer,thebufferinfos, -1, -1);
  if InputIndex1 > -1 then
  begin
      uos_EndProc(PlayerIndex1, @ClosePlayer);
      OutputIndex1 := uos_addIntoFile(PlayerIndex1, Pchar('/home/user/MyWav.wav'), -1,1,1,-1,1 ); //
      if OutputIndex1 > -1 then
        uos_Play(PlayerIndex1);
  end;

I get the next time dependence



Then I opened wav file with thebufferinfos.SampleFormat = 1
 by the route

  Res := uos_LoadLib(Pchar(PA_FileName), Pchar(SF_FileName), pchar(MP_FileName), nil, nil, nil) ;
  If Res=0 Then
    thebuffer := uos_File2Buffer(pchar(SoundFilename), 1, thebufferinfos, -1, -1);

I get the next time dependence of sound sygnal



But after saving buffer by standard route I get such time dependence



Note! The signal saves timbre voice but is two times shorter!

When I opened wav file with thebufferinfos.SampleFormat = 2
 by the route

  Res := uos_LoadLib(Pchar(PA_FileName), Pchar(SF_FileName), pchar(MP_FileName), nil, nil, nil) ;
  If Res=0 Then
    thebuffer := uos_File2Buffer(pchar(SoundFilename), 2, thebufferinfos, -1, -1);

I get the next time dependence of sound signal



But after saving buffer by standard route I get such time dependence



Does it mean that I shoud open wav file with one value SampleFormat and save it with an other value?
How to find parameters for opening and saving buffer in wave file of 16 bit?
Maybe I'd better work with other sound formats to use UOS?
Thanks for the answer.
Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
In reply to this post by Dan Mistrenko
Hello.

Did you try the demo /uos/SimpleRecorder.lpi ?

Is it working when you save it ?

What is your OS (Linux, Windows? Raspbian, FreeBSD, ...) ?

When creating the buffer what kind of file is SoundFilename?
 thebuffer := uos_File2Buffer(pchar(SoundFilename), 0, thebufferinfos, -1, -1);

> How to find parameters for opening and saving buffer in wave file of 16 bit?

Please read my previous post:

function uos_AddIntoFile(PlayerIndex: cint32; Filename: PChar; SampleRate: cint32;
  Channels: cint32; SampleFormat: cint32 ; FramesCount: cint32 ; FileFormat: cint32): cint32;
// Add a Output into audio wav file with custom parameters from TFileStream
// PlayerIndex : Index of a existing Player
// FileName : filename of saved audio wav file
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (1:mono, 2:stereo, ...)
// SampleFormat : default : -1 (2:Int16) (1:Int32, 2:Int16)
// FramesCount : default : -1 (= 65536)
// FileFormat : default : -1 (wav) (0:wav, 1:pcm, 2:custom);
//  result :Output Index in array  -1 = error

function uos_File2Buffer(Filename: Pchar; SampleFormat: cint32 ; var bufferinfos: Tuos_BufferInfos ; frompos : cint; numbuf : cint ): TDArFloat;
// Create a memory buffer of a audio file.
// FileName : filename of audio file  
// SampleFormat : default : -1 (1:Int16) (0: Float32, 1:Int32, 2:Int16)
// bufferinfos : the infos of the buffer.
// frompos : from position (default : -1 = from begining, otherwise position in song)
// numbuf : number of frames to add to outmemory (default : -1 = all, otherwise number max of frames)
//  result :  The memory buffer
 
> Maybe I'd better work with other sound formats to use UOS?

What sound format are you using?

It would be much easier for me to help you if you give a complete code of what you want to do.

Fre;D






Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
In reply to this post by fredvs
Re-hello.

Could you please take a look at /uos/consoleplaymemorybuffer.lpi demo?

Here the code adapted to save to file, I get a wav file correct (see attachment):
MyWav.wav   

....
   ordir := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0)));

   SoundFilename := ordir + 'sound/test.wav';

  res := uos_LoadLib(Pchar(PA_FileName), Pchar(SF_FileName), nil, nil, nil, nil) ;

    writeln('Result of loading (if 0 => ok ) : ' + IntToStr(res));

   if res = 0 then begin
       PlayerIndex1 := 0;

    // Create a memory buffer from a audio file
    thebuffer := uos_File2Buffer(pchar(SoundFilename), 1, thebufferinfos, -1, -1);
         
    // You may store that buffer into ressource...
    // ... and when you get the buffer from ressource....
   
    uos_CreatePlayer(PlayerIndex1);
   
    // Add a input from memory buffer with custom parameters
  input1 := uos_AddFromMemoryBuffer(PlayerIndex1,thebuffer,thebufferinfos, -1, 1024);

// here add into file:      
   uos_addIntoFile(PlayerIndex1, Pchar('/home/fred/MyWav.wav'), -1,1,1,-1,1 ); //
   
// everything is ready, here we are, lets play it...

 uos_Play(PlayerIndex1);
 
    sleep(2000);
    end;

 end;
Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
Re-hello.

If I know exactly what you want to achieve, it would be great.

Why do you need to convert the wav file into buffer?

You may also use uos_AddFromMemoryStream(), please take a look at demo /uos/consoleplaymemorystream.lpi.

Fre;D
 
Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

Dan Mistrenko
Hello Fre;D

Thanks for the answer.
I work in Xubuntu 16.04, Lazarus 2.0.2 or 2.0.10.

I studied the codes consoleplaymemorybuffer.lpi but if I work on graphical environment SampleFormat works differently.
I want to understand where is a mistake.

Here is my project:
sonar_201109.lpi
sonar_201109.lpr
unit1.pas
unit1.lfm
Unit_Kernel.pas

Here wav file to transform
Mimo_Kat_44100kH_16bit_001.wav

I work with open source cross-platform project on Lazarus for speech processing. Then I need get access to transform buffer for saving it in different files.
Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
This post was updated on .
Hello.

Ok, I think I get it.

There was indeed a problem with SaveToFile if the buffer is mono.
Thanks to note it.
It was fixed on last commit of uos:  


This code, adapted from the consoleplaybuffer demo works for me:
But you need last commit of uos.


   SoundFilename := '/home/fred/Downloads/Mimo_Kat_44100kH_16bit_001.wav';

       PlayerIndex1 := 0;

    // Create a memory buffer from a audio file
    thebuffer := uos_File2Buffer(pchar(SoundFilename), 1, thebufferinfos, -1, -1);
         
    uos_CreatePlayer(PlayerIndex1);
   
    // Add a input from memory buffer with custom parameters
  input1 := uos_AddFromMemoryBuffer(PlayerIndex1,thebuffer,thebufferinfos, -1, 1024);

   // add a Output into device with default parameters
  {$if defined(cpuarm)} // needs lower latency
        uos_AddIntoDevOut(PlayerIndex1, -1, 0,3, uos_inputgetSampleRate(PlayerIndex1,input1),
  uos_inputgetChannels(PlayerIndex1,input1) , 0, 1024, -1);
       {$else}
     uos_AddIntoDevOut(PlayerIndex1, -1, -1, uos_inputgetSampleRate(PlayerIndex1,input1),
  uos_inputgetChannels(PlayerIndex1,input1) , 0, 1024, -1);
       {$endif}
     
     // Add into file    
  uos_addIntoFile(PlayerIndex1, Pchar('/home/fred/testwav.wav'), -1,1,1,1024,-1 );
   
     /////// everything is ready, here we are, lets play it...

 uos_Play(PlayerIndex1);
 
    sleep(2000);
    end;


I hope it will solve your problems, otherwise, dont hesitate to say it.

Fre;D

[EDIT]

Included the result of the saved file from Mimo_Kat_44100kH_16bit_001.wav
testwav.wav
Reply | Threaded
Open this post in threaded view
|

Re: How to save WAV file from buffer?

fredvs
Administrator
This post was updated on .
Re-hello.

The previous demo saves the buffers in wav file with 32 bit format.

If you want a wav 16 bit, this works here too (note the format param set to 2 = integer 16 bit):

    SoundFilename :=  '/home/fred/Downloads/Mimo_Kat_44100kH_16bit_001.wav';

    // Create a memory buffer from a audio file
    thebuffer := uos_File2Buffer(pchar(SoundFilename), 2, thebufferinfos, -1, -1);
         
    // You may store that buffer into ressource...
    // ... and when you get the buffer from ressource....
   
    uos_CreatePlayer(PlayerIndex1);
   
    // Add a input from memory buffer with custom parameters
  input1 := uos_AddFromMemoryBuffer(PlayerIndex1,thebuffer,thebufferinfos, -1, 1024);

   // add a Output into device with default parameters

  {$if defined(cpuarm)} // needs lower latency
        uos_AddIntoDevOut(PlayerIndex1, -1, 0,3, uos_inputgetSampleRate(PlayerIndex1,input1),
  uos_inputgetChannels(PlayerIndex1,input1) , 2, 1024, -1);
       {$else}
     uos_AddIntoDevOut(PlayerIndex1, -1, -1, uos_inputgetSampleRate(PlayerIndex1,input1),
  uos_inputgetChannels(PlayerIndex1,input1) , 2, 1024, -1);
       {$endif}
     
// {  // Save to file    
   uos_addIntoFile(PlayerIndex1, Pchar(ordir + 'testwav16.wav'),
   uos_inputgetSampleRate(PlayerIndex1,input1),
   uos_inputgetChannels(PlayerIndex1,input1),-1,1024,-1 ); //
 // }  
 
    /////// everything is ready, here we are, lets play it...

 uos_Play(PlayerIndex1);
 
    sleep(2000);
    end;

/////
Here  testwav16.wav result:
testwav16.wav