Recent

Author Topic: [SOLVED] Capture sound from line in or microphone  (Read 7739 times)

CM630

  • Hero Member
  • *****
  • Posts: 1195
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
[SOLVED] Capture sound from line in or microphone
« on: June 06, 2024, 07:58:34 am »
I want to capture sound from line in or the microphone and store it in an array.

I came across BASS24 and ACS.
There is a working source with https://sourceforge.net/p/wp-laz/code/HEAD/tree/Oscilloscope/trunk/. It is too complex, there are chances that I can make out how to use it, but I am not sure and it will probably take days.
ACS https://github.com/serbod/acs is updated 4 months ago, but none of its recording examples work.
Could I use something else?
« Last Edit: June 18, 2024, 01:29:37 pm by CM630 »
Лазар 4,0RC1 32 bit (sometimes 64 bit); FPC3,2,2

cdbc

  • Hero Member
  • *****
  • Posts: 1655
    • http://www.cdbc.dk
Re: Capture sound from line in or microphone
« Reply #1 on: June 06, 2024, 09:37:56 am »
Hi
Sadly, the ACS will take you a long time, to get into working order...
If you're on *nix, I would suggest having a look at @Fred vS' UOS library: https://github.com/fredvs/uos
If you're on winders, I've heard good things about the BASS library: https://www.un4seen.com/
Just my 2 cents worth  :)
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: Capture sound from line in or microphone
« Reply #2 on: June 06, 2024, 09:43:51 am »
User lulu created ALSound which seems simple enough to use, support multiple platforms and all used software is open source.

An simple console recording example can be found here.

Note that you can do without the extra libraries and solely depend on libopenal but then you would have to write some additional code yourself.
« Last Edit: June 06, 2024, 09:45:33 am by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Fred vS

  • Hero Member
  • *****
  • Posts: 3411
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #3 on: June 06, 2024, 10:53:47 am »
Hello.
If you're on *nix, I would suggest having a look at @Fred vS' UOS library: https://github.com/fredvs/uos
uos works for Windows, Linux, FreeBSD and MacOS.
You may take a look at the demo uos/examples/simplerecorder.lpi

[EDIT]: About a oscilloscope code, there is WavvieW, it uses uos.
« Last Edit: June 06, 2024, 01:45:46 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

CM630

  • Hero Member
  • *****
  • Posts: 1195
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #4 on: June 06, 2024, 04:00:06 pm »

I have tried it.
Writing to WAV works fine.
I have uncommented these lines:



Code: Pascal  [Select][+][-]
  1.      SetLength(thebuffer, 0);
  2.      uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer);

but I get no corresponding data in thebuffer, there is a graph with the data, I have exported it to CSV - Excel draws the same curve.


Code: Pascal  [Select][+][-]
  1.     // saving in a file using a File-Stream:
  2.      uos_AddIntoFile(PlayerIndex1, PChar(edit3.Text), -1, -1, -1, 4096, outformat);
  3.  
  4.  
  5.  //   function uos_AddIntoFile(PlayerIndex: cint32; Filename: PChar; SampleRate: cint32;
  6.  // Channels: cint32; SampleFormat: cint32 ; FramesCount: cint32 ; FileFormat: cint32): cint32;
  7. // Add a Output into audio wav file with custom parameters from TFileStream
  8. // PlayerIndex : Index of a existing Player
  9. // FileName : filename of saved audio wav file
  10. // SampleRate : delault : -1 (44100)
  11. // Channels : delault : -1 (2:stereo) (1:mono, 2:stereo, ...)
  12. // SampleFormat : default : -1 (2:Int16) (1:Int32, 2:Int16)
  13. // FramesCount : default : -1 (= 65536)
  14. // FileFormat : default : -1 (wav) (0:wav, 1:pcm, 2:custom, 3:ogg);
  15.  
  16.  
  17.     //// add Output into wav or ogg file (save record) from TFileStream
  18.  
  19.  
  20.     // saving in a Memory-Buffer:  
  21.      SetLength(thebuffer, 0);
  22.      uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer);            


EDIT: I just saw about WavieW, I will try it.
« Last Edit: June 06, 2024, 04:10:45 pm by CM630 »
Лазар 4,0RC1 32 bit (sometimes 64 bit); FPC3,2,2

Fred vS

  • Hero Member
  • *****
  • Posts: 3411
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #5 on: June 06, 2024, 04:23:46 pm »
Hello CM630.

Not sure to understand.

Do you want to save the input into a wav (or ogg) file and also save the input into a buffer?
I did not try this yet, only with input into a wav (or ogg) file or save the input into a buffer.

Did you try with only uos_AddIntoMemoryBuffer(), without uos_AddIntoFile()?

There are also other ways to save the input samples:
   
Code: Pascal  [Select][+][-]
  1.     // saving in a Memory-Buffer:  
  2.     // SetLength(thebuffer, 0);
  3.     // uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer);
  4.  
  5.     // saving in a Memory-Stream:  
  6.     // if thememorystream = nil then thememorystream := tmemorystream.create;
  7.     // uos_AddIntoMemoryStream(PlayerIndex1, (thememorystream),-1,-1,-1,-1);
  8.    
« Last Edit: June 06, 2024, 05:26:53 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

CM630

  • Hero Member
  • *****
  • Posts: 1195
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #6 on: June 07, 2024, 08:49:01 am »
I do not want to save the input to WAV, I want to get the data in array (or in two arrays, if I use two 1D arrays per each channel).
This way I could display, analyse and manipulate the data. And store it to whatever format I want.
It would be better if I could retrieve the currently retrieved audio without interrupting the retrieval of the data.


Quote
Did you try with only uos_AddIntoMemoryBuffer(), without uos_AddIntoFile()?

I did, I get the same result ;(


Quote
There are also other ways to save the input samples:

Since uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer); gives no result,
I will try uos_AddIntoMemoryStream, I suppose there is a way to convert a memory stream into an array. But that is a virtual WAV file, maybe the result will be encoding and then decoding, which could result in useless oprations.
Even if it works, I will have to know how to separate the left and the right channel.

I downloaded WavieW, it has no lpr and lpi files, compiling it will be hard, but hopefully possible.



In he worst case I could use
Code: Pascal  [Select][+][-]
  1. DynArrayOfSamples := uos_File2Buffer(pchar(SoundFilename), int16 , BufferInfo, FromPos, NumSamples);
and read the WAV, which I do not need into an array.
« Last Edit: June 07, 2024, 09:32:22 am by CM630 »
Лазар 4,0RC1 32 bit (sometimes 64 bit); FPC3,2,2

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: Capture sound from line in or microphone
« Reply #7 on: June 07, 2024, 09:37:10 am »
I suppose there is a way to convert a memory stream into an array.
A memory stream is an array. See also Documentation.

It is described as being a pointer but you can cast it to whatever you want to f.e. to a PByte which can then be accessed using PByte(MMstream.Memory)[byteindex];

Quote
Even if it works, I will have to know how to separate the left and the right channel.
Splitting channels is trivial. I could not find a good example so quickly (graphical layouts usually works better in this case) but it is explained f.e. here. Do note that the storage format can differ between different programs/API's/formats.
« Last Edit: June 07, 2024, 09:43:18 am by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Fred vS

  • Hero Member
  • *****
  • Posts: 3411
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #8 on: June 07, 2024, 11:38:30 am »
Hello CM630.

Sad that it dont work for you and sad that I dont have my laptop till next week to test.

Maybe you may test assigning a other sample format of the input:

Code: Pascal  [Select][+][-]
  1. function uos_AddFromDevIn(PlayerIndex: cint32; Device: cint32; Latency: CDouble;
  2.   SampleRate: CDouble; OutputIndex: cint32;
  3.   SampleFormat: cint32; FramesCount : cint32; ChunkCount: cint32): cint32;
  4. // Add a Input from Device Input with custom parameters
  5. // PlayerIndex : Index of a existing Player
  6. // Device ( -1 is default Input device )
  7. // Latency  ( -1 is latency suggested ) )
  8. // SampleRate : delault : -1 (44100)
  9. // Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
  10. // OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex  (if multi-output then OutName = name of each output separeted by ';')
  11. // SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
  12. // FramesCount : default : -1 (65536)
  13. // ChunkCount : default : -1 (= 512)
  14.  

So for the simplerecorder demo it would be:

For intput float 32 sample:
Code: Pascal  [Select][+][-]
  1. In1Index :=  uos_AddFromDevIn(PlayerIndex1,-1, -1, -1, -1, 0, -1, -1);

For intput integer 32 sample:
Code: Pascal  [Select][+][-]
  1. In1Index :=  uos_AddFromDevIn(PlayerIndex1,-1, -1, -1, -1, 1, -1, -1);

For intput integer 16 sample:
Code: Pascal  [Select][+][-]
  1. In1Index :=  uos_AddFromDevIn(PlayerIndex1,-1, -1, -1, -1, 2, -1, -1);

Quote
I downloaded WavieW, it has no lpr and lpi files, compiling it will be hard, but hopefully possible.

WavvieW is a MSEgui program and has .prj file for project.

I am really sorry but I cannot do any test before next week.

I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Thaddy

  • Hero Member
  • *****
  • Posts: 16168
  • Censorship about opinions does not belong here.
Re: Capture sound from line in or microphone
« Reply #9 on: June 07, 2024, 11:49:24 am »
Fred, he mixes up the sample rates and confuses integer with floats on top of that.
Your code is OK.
If I smell bad code it usually is bad code and that includes my own code.

CM630

  • Hero Member
  • *****
  • Posts: 1195
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #10 on: June 07, 2024, 02:49:20 pm »
...

For intput float 32 sample:
Code: Pascal  [Select][+][-]
  1. In1Index :=  uos_AddFromDevIn(PlayerIndex1,-1, -1, -1, -1, 0, -1, -1);

For intput integer 32 sample:
Code: Pascal  [Select][+][-]
  1. In1Index :=  uos_AddFromDevIn(PlayerIndex1,-1, -1, -1, -1, 1, -1, -1);

For intput integer 16 sample:
Code: Pascal  [Select][+][-]
  1. In1Index :=  uos_AddFromDevIn(PlayerIndex1,-1, -1, -1, -1, 2, -1, -1);
...
I tried them, the sound became odd.
But by default, the output is int16, while thebuffer is array of cfloat;
Now it started to look somehow similar, except that there are some periodic “noises”.
I was expecting that what comes as input is simply voltage values like it comes from a regular DAQ, but maybe it is something else.

There is nothing urgent, considering that lately PCs have no LineIn inputs, maybe it makes absolutely no sense.
« Last Edit: June 07, 2024, 02:55:18 pm by CM630 »
Лазар 4,0RC1 32 bit (sometimes 64 bit); FPC3,2,2

Thaddy

  • Hero Member
  • *****
  • Posts: 16168
  • Censorship about opinions does not belong here.
Re: Capture sound from line in or microphone
« Reply #11 on: June 07, 2024, 02:55:23 pm »
The reason why input and output are generally either 16 or 24 bit integers is that audio hardware dac's and adc's work like that.
The reason to process the data internally as floats (either single or double usually) is that the internal processing has way more precision and so keeps a cleaner signal.
But you should not mix up the two: as I already suspected, you actually do just that.
Apart from latency issues - and Fred is aware of that and is not always an issue - Fred's unifying code is excellent.

Speed is not an issue here: optimized code for buffer conversions, even on 25 year old hardware, introduces just about 2 Ms of delay in total, back and forth, which is to human ears impossible to hear. That starts at around 25 Ms.

BTW: the line in is almost always there, usually nowadays over a USB type interface.
« Last Edit: June 07, 2024, 03:16:21 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

Fred vS

  • Hero Member
  • *****
  • Posts: 3411
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #12 on: June 07, 2024, 03:23:06 pm »
Quote
>But by default, the output is int16, while thebuffer is array of cfloat;

Indeed and Thaddy explained perfectly why (mainly for more precision while rounded only at end of calculation).
But a array of cfloat can store initial integer value.

Quote
>I tried them, the sound became odd.

It can be because maybe you did not assign the same sample format for the input and the output.

Anyway, without my PC this are only speculations, next week I will jump into it and see why you get problems.
I apologize that I cannot help you now.

Thaddy: Thanks for the nice flowers. ;-)

Fre;D
« Last Edit: June 07, 2024, 03:25:11 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

CM630

  • Hero Member
  • *****
  • Posts: 1195
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #13 on: June 07, 2024, 03:54:37 pm »
Thanks for the efforts and advice, at least the worst solution works (almost, since the app crashed on the second attempt).

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. var
  3.   myarray : array of single;
  4.   BufferInfo : TuosF_BufferInfos;
  5. begin
  6.   uos_Stop(PlayerIndex1);
  7.   ClosePlayer1;
  8. ...
  9.   myarray := uos_File2Buffer(pchar(Edit3.Text), 0 , BufferInfo, -1, -1);
  10. ...
  11. end;
« Last Edit: June 07, 2024, 03:57:05 pm by CM630 »
Лазар 4,0RC1 32 bit (sometimes 64 bit); FPC3,2,2

Thaddy

  • Hero Member
  • *****
  • Posts: 16168
  • Censorship about opinions does not belong here.
Re: Capture sound from line in or microphone
« Reply #14 on: June 07, 2024, 04:02:50 pm »
Where is the setlength for myarray?
Why do you not set it to a fixed length array if you know the buffer size that you need?
There are many things going wrong in that code, even without seeing it all.

To quote Hamlet again:
“There are more things in heaven and earth, Horatio, than are dreamt of in your philosophy.”

You can calculate the buffer size from my signature... ;)

(RANT ALERT!! btw, about audio programming: I wrote the original ASIO interface for object pascal 23 years ago, TobyBear helped to get it right, and Christian still claims he wrote it... false.
The original VST interface was written by Frederic VanMol, btw... also stolen without reference..
Christian did much good, but he is not very reliable in mentioning original sources.
I also wrote the Pascal translation of the reverb3 from Jazar (still the best analog reverb emulation). Again Christian claims that code as his, furthermore it is identical, including my comments. Even if you write freeware it is good to acknowledge the original author. Those sources still exist and are available from  OPM, the asiovst package. People who steal code should at least remove the comments...
Both Tobias and I have nothing to do with that, just Christian -what's in a name?)
« Last Edit: June 07, 2024, 04:36:30 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

 

TinyPortal © 2005-2018