Recent

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

Fred vS

  • Hero Member
  • *****
  • Posts: 3505
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #15 on: June 07, 2024, 04:07:37 pm »
Quote
at least the worst solution works

I am happy that you found a provisory solution.

Quote
(almost, since the app crashed on the second attempt).

Could you try with:

 
Code: Pascal  [Select][+][-]
  1.  uos_Stop(PlayerIndex1);
  2.   application.processmessages;
  3.   sleep(100);
  4.   myarray := uos_File2Buffer(pchar(Edit3.Text), 0 , BufferInfo, -1, -1);
  5.  

But we will find a nicer solution 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

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #16 on: June 07, 2024, 04:35:11 pm »
...
Quote
(almost, since the app crashed on the second attempt).
Could you try with:
Code: Pascal  [Select][+][-]
  1.  uos_Stop(PlayerIndex1);  application.processmessages;  sleep(100);  myarray := uos_File2Buffer(pchar(Edit3.Text), 0 , BufferInfo, -1, -1);
...

Maybe something goes wrong with my visualisation routine.
If write the WAV as mono, with my visualization the app crashes when writing the WAV, without it it does not. Stereo has no problems, but still I have not got to separating the tracks, so I prefer mono.
Without my visualization, nothing crashes.

I will try next week and feedback.



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

 
Code: Pascal  [Select][+][-]
  1. myarray := uos_File2Buffer(pchar(Edit3.Text), 0 , BufferInfo, -1, -1);

is a single line of code, so you have seen it all.
The size of myarray depends on the contents of the file, which I do not know before reading it.
uos_File2Buffer seems to take care of the size of the array.
« Last Edit: June 07, 2024, 04:43:44 pm by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

Thaddy

  • Hero Member
  • *****
  • Posts: 16659
  • Kallstadt seems a good place to evict Trump to.
Re: Capture sound from line in or microphone
« Reply #17 on: June 07, 2024, 04:51:02 pm »
Creating mono from stereo is easy and best done in the integer domain:
You add up left sample and right sample and integer divide it by 2.
But it HAS to be done. You can also choose to use either left or right channel by skipping one channel. That is also easy because the wav format encodes both on the same line, so a 16 bit encoding is stereo 32 bit and left is the upper word and right is the lower word.
On some older systems (8 bit) adapt for that.
Since that is essentially a vector transform, the modern Freepascal compiler generates very fast code for it.
No need for the olden days.
« Last Edit: June 07, 2024, 05:01:05 pm by Thaddy »
But I am sure they don't want the Trumps back...

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #18 on: June 07, 2024, 04:55:58 pm »
Could you try with:

 
Code: Pascal  [Select][+][-]
  1.  uos_Stop(PlayerIndex1);
  2.   application.processmessages;
  3.   sleep(100);
  4.   myarray := uos_File2Buffer(pchar(Edit3.Text), 0 , BufferInfo, -1, -1);
  5.  
I tried, no change. But ClosePlayer1 already does that:


Code: Pascal  [Select][+][-]
  1. procedure TForm1.ClosePlayer1;
  2. begin
  3.   sleep(500);
  4.   application.ProcessMessages;
  5.   button2.Enabled   := True;
  6.   button3.Enabled   := False;
  7.   button5.Enabled   := False;
  8.   CheckBox1.Enabled := True;
  9.   CheckBox2.Enabled := True;
  10.   if CheckBox2.Checked = True then
  11.     Button4.Enabled := True;
  12. end;


It crashes in


Code: Pascal  [Select][+][-]
  1. procedure tuosthread.execute
  2. ...
  3.  else// No plugin
  4.                                            WriteOut(x, x2);  ...
  5.  


« Last Edit: June 07, 2024, 04:59:22 pm by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

Thaddy

  • Hero Member
  • *****
  • Posts: 16659
  • Kallstadt seems a good place to evict Trump to.
Re: Capture sound from line in or microphone
« Reply #19 on: June 07, 2024, 05:02:47 pm »
Unless I see more - complete, at least reproducable - code, I can not help you any further.
But I am sure they don't want the Trumps back...

Fred vS

  • Hero Member
  • *****
  • Posts: 3505
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #20 on: June 07, 2024, 05:10:33 pm »
Quote
If write the WAV as mono, with my visualization the app crashes when writing the WAV

Sorry but what is your visualization?
Is it called by a uos-loop method?

Note that you cannot force the input to mono if you sound-card has a stereo input.
If you want a mono result "live" take a look at SimplePlayer demo, there is a DSP stereo to mono.

Maybe if you give the code of your attempt it would be easier to find solutions (next week).
« Last Edit: June 07, 2024, 05:12:50 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: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #21 on: June 07, 2024, 07:08:23 pm »
Sorry but what is your visualization?

It is a control, based on TAChart. It is in sourceforge, but it is incomplete. It has nothing to do with uos, etc.


Note that you cannot force the input to mono if you sound-card has a stereo input.

I am pretty sure that the microphone of my headphones is mono, but maybe for some reason it sends the sound as stereo.

I wanted to save the sound to mono, because as I expected that mono would require less efforts.
For example
   myarray := uos_File2Buffer(pchar(Edit3.Text), 0 , BufferInfo, -1, -1);
returns (probably) all channels to myarray. They might be 1; 2; 7;8 (at least these are the most usual number of channels).
And I do not know how to separate them.

I just wanted to make an example for my visualization control capturing data from the sound card.
I expected that there might be some snippets:
Code: Pascal  [Select][+][-]
  1.    data:= get_audio_data(source);
  2.    plot_to_stringgrid(left_channel);
  3.    plot_to_stringgrid(right_channel);
  4.  

I have no reason to understand how audio works, and I did not expect that I would need to.
So please do not spend more time on that, unless you have no internal necessity to do it.
Of course, I would gladly use a solution, if available.
« Last Edit: June 07, 2024, 07:10:13 pm by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

Thaddy

  • Hero Member
  • *****
  • Posts: 16659
  • Kallstadt seems a good place to evict Trump to.
Re: Capture sound from line in or microphone
« Reply #22 on: June 07, 2024, 07:24:52 pm »
Well, if you want to plot audio, you really need to understand how audio formats work.
Actually, you only need to know how raw audio formats work.
Then it is just a matter of scaling back both resolution and time to the required display resolution. Both of which are easy:
Resolution:
- scale back from 44100/48000/higher samples per second to let's say 512 pixels. That means you throw away most of the data anyway, so you can take shortcuts.
- scale back the timing in the same way, so both are in sync. Again, easy.

If you want to plot audio, you really need to know how audio works. There are no shortcuts.
I have some old KOL controls lying around that can help you. See if I can still find them after all these years. (KOL back to VCL/LCL is easy)

Wait...
The AsioVst package contains that code. Simply get it from OPM.
Note it is definitely NOT cross platform and definitely works best - or only - on 32 bit Windows, but the sourcecode may help you anyway. We wrote it over 20 years ago....
There is also some useful code in the musicdsp archives by me and by Tobias. (again, way more than 20 years old). The code by Tobias in his audio filter design program is probably the best of that. It is still a treasure for Object Pascal audio programmers.
What Christian did right is to bundle it.

Another good example for audio code is the dcp-dsp package which is available from Torry's. Also more than 20 years old.

[edit]
I see that dcp-dsp needs some {$mode delphi} injected, but the code is written in D5 and D7 so will compile in FPC/Lazarus too.
« Last Edit: June 08, 2024, 12:15:01 am by Thaddy »
But I am sure they don't want the Trumps back...

Fred vS

  • Hero Member
  • *****
  • Posts: 3505
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #23 on: June 09, 2024, 12:01:54 am »
Hello CM630

Could you try changing this:
 
Code: Pascal  [Select][+][-]
  1.  uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer);

with this:
Code: Pascal  [Select][+][-]
  1.   uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer, -1, 0, -1, -1);
     
You should get the same buffer as with uos_File2Buffer(). (but not needed anymore).
If it is ok with the change for you, I will update the default sample format to float32 for uos_AddIntoMemoryBuffer(PlayerIndex, @abuffer);

The buffer will be stereo, if you want to convert into mono you could do like this in the close button:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. var
  3.   mymonoarray : array of single;
  4.   x, y : integer;
  5.  begin
  6.   uos_Stop(PlayerIndex1);
  7.   ClosePlayer1;
  8.  
  9.    setlength(mymonoarray, Length(thebuffer) div 2);
  10.  
  11.    x := 0;
  12.    y := 0;
  13.  
  14.   while x < length(mymonoarray) do
  15.   begin
  16.   mymonoarray[x] := (thebuffer[y] + thebuffer[y+1]) /2;
  17.   x := x + 1 ;
  18.   y := y + 2;
  19.   end;
  20.  
  21. end;


« Last Edit: June 09, 2024, 12:34:01 am 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: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #24 on: June 09, 2024, 09:56:56 am »
Thanks, I will try on Monday, when I get to the PC.
I do not want to downmix stereo to mono, I want to separate the channels.
What I get from your example is that the samples with even indeces [0;2;4;6....] are the left channel, the other samples are for the right one (or vice versa), so separation will be easy.
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

Fred vS

  • Hero Member
  • *****
  • Posts: 3505
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #25 on: June 09, 2024, 02:00:18 pm »
Hello CMP630.

Quote
I want to separate the channels.
Ha, ok, then something like this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. var
  3.   arrayleft, arrayright : array of single;
  4.   x, y : integer;
  5.  begin
  6.   uos_Stop(PlayerIndex1);
  7.   ClosePlayer1;
  8.  
  9.    setlength(arrayleft, Length(thebuffer) div 2);
  10.    setlength(arrayright, Length(arrayleft));
  11.  
  12.    x := 0;
  13.    y := 0;
  14.  
  15.   while x < length(arrayleft) do
  16.   begin
  17.    arrayleft[x]   := thebuffer[y];
  18.    arrayright[x] := thebuffer[y+1];
  19.    x := x + 1 ;
  20.    y := y + 2;
  21.   end;
  22. end;


Quote
What I get from your example is that the samples with even indeces [0;2;4;6....] are the left channel, the other samples are for the right one
Yes, you get it!
The array has this order:
Code: Pascal  [Select][+][-]
  1. Sample1_Channel1, Sample1_Channel2, Sample1_Channel3,..,Sample1_ChannelN,
  2. Sample2_Channel1, Sample2_Channel2, Sample2_Channel3,..,Sample2_ChannelN,
  3. Sample3_Channel1, Sample3_Channel2, Sample3_Channel3,..,Sample3_ChannelN,
  4. ...
  5. SampleLast_Channel1, SampleLast_Channel2, SampleLast_Channel3,..,SampleLast_ChannelN;
And so for a stereo array (2 channels):
Code: Pascal  [Select][+][-]
  1. Sample1_Left, Sample1_Right, Sample2_Left, Sample2_Right, Sample3_Left, Sample3_Right,
  2. ...
  3. SampleLast_Left, SampleLast_Right;


Quote
I am pretty sure that the microphone of my headphones is mono, but maybe for some reason it sends the sound as stereo.
To get the number of channels of a input, you may also use, after uos_AddFromDevIn(),: uos_InputGetChannels():
Code: Pascal  [Select][+][-]
  1. function uos_InputGetChannels(PlayerIndex: cint32; InputIndex: cint32): cint32;
« Last Edit: June 09, 2024, 07:05:25 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: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Capture sound from line in or microphone
« Reply #26 on: June 10, 2024, 09:12:26 am »
Still not working.
I refreshed the sources from GIT, so these are the only changed things:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button2Click(Sender: TObject);    
  2.   ...
  3.    //     uos_AddIntoFile(PlayerIndex1, PChar(edit3.Text), -1, -1, -1, 4096, outformat); //Commenting or uncommenting this line seems to make no difference.
  4.  ...
  5.     // saving in a Memory-Buffer:  
  6.     SetLength(thebuffer, 0);
  7.     uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer, -1, 0, -1, -1);
  8. ...
  9.  
  10.  
  11. procedure TForm1.Button3Click(Sender: TObject);
  12. var
  13.   i, j: integer;
  14.   arrayleft, arrayright : array of double;
  15.   f : double = 1{/44000};
  16. begin
  17.   uos_Stop(PlayerIndex1);
  18.   ClosePlayer1;
  19.   Chart1LineSeriesLeft.Clear;
  20.   Chart1LineSeriesRight.Clear;
  21.  
  22.  
  23.   setlength(arrayleft, Length(thebuffer) div 2);
  24.   setlength(arrayright, Length(arrayleft));
  25.  
  26.  
  27.   i := 0;
  28.   j := 0;
  29.  
  30.  
  31.   while i < length(arrayleft) do
  32.   begin
  33.     arrayleft[i]  := Double(thebuffer[j]);
  34.     arrayright[i] := Double(thebuffer[j+1]);
  35.     Chart1LineSeriesLeft.AddXY(i/f,arrayleft[i],'',clRed);
  36.     Chart1LineSeriesRight.AddXY(i/f,arrayright[i],'',clBlue);
  37.     i := i + 1;
  38.     j := j + 2;
  39.   end;
  40.   WaveformGraph1.ClearPlots;
  41.   WaveformGraph1.Plot(arrayleft,f,clRed);
  42.   WaveformGraph1.Plot(arrayright,f, clBlue);
  43. end;  


The left graph is made with TAChart, the right one is with my control, to make sure that I am not doing anything wrong.
« Last Edit: June 10, 2024, 09:17:11 am by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

TRon

  • Hero Member
  • *****
  • Posts: 4158
Re: Capture sound from line in or microphone
« Reply #27 on: June 10, 2024, 10:14:43 am »
Hi CM630,

If I understood you correctly then you could perhaps take a look at this.
Today is tomorrow's yesterday.

Thaddy

  • Hero Member
  • *****
  • Posts: 16659
  • Kallstadt seems a good place to evict Trump to.
Re: Capture sound from line in or microphone
« Reply #28 on: June 10, 2024, 10:24:24 am »
TAchart is way to slow to keep up with live audio anyway. I usualy draw on a canvas directly, most of my KOL audio display stuff works like that.
But I am sure they don't want the Trumps back...

Fred vS

  • Hero Member
  • *****
  • Posts: 3505
    • StrumPract is the musicians best friend
Re: Capture sound from line in or microphone
« Reply #29 on: June 10, 2024, 12:01:49 pm »
Hello CP630

Sad that it does not work for you.
But in a previous post you said that it was working with the workaround using myarray:
Code: Pascal  [Select][+][-]
  1. myarray := uos_File2Buffer(pchar(Edit3.Text), 0 , BufferInfo, -1, -1);

Did you try to use thebuffer without splitting it, like you did for the workaround?
Code: Pascal  [Select][+][-]
  1.   uos_AddIntoMemoryBuffer(PlayerIndex1, @thebuffer, -1, 0, -1, -1);

thebuffer and myarray should be the same (here it is he case). 

Also, could you check the result of num input channel, you could do something like this:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. var
  3.   i, j, nchan: integer;
  4.   arrayleft, arrayright : array of double;
  5.   f : double = 1{/44000};
  6. begin
  7.   nchan := uos_InputGetChannels(PlayerIndex1, In1Index); // this to check nb of channels
  8.   uos_Stop(PlayerIndex1);
  9.   ClosePlayer1;
  10.  
  11.   Chart1LineSeriesLeft.Clear;
  12.   Chart1LineSeriesRight.Clear;
  13.  
  14. if nchan > 1 then // this to split if stereo
  15.  begin
  16.   setlength(arrayleft, Length(thebuffer) div 2);
  17.   setlength(arrayright, Length(arrayleft));
  18.  
  19.   i := 0;
  20.   j := 0;
  21.  
  22.   while i < length(arrayleft) do
  23.   begin
  24.     arrayleft[i]  := Double(thebuffer[j]);
  25.     arrayright[i] := Double(thebuffer[j+1]);
  26.     Chart1LineSeriesLeft.AddXY(i/f,arrayleft[i],'',clRed);
  27.     Chart1LineSeriesRight.AddXY(i/f,arrayright[i],'',clBlue);
  28.     i := i + 1;
  29.     j := j + 2;
  30.   end;
  31.   WaveformGraph1.ClearPlots;
  32.   WaveformGraph1.Plot(arrayleft,f,clRed);
  33.   WaveformGraph1.Plot(arrayright,f, clBlue);
  34.  end
  35. else  // it is mono dont split the array
  36. begin
  37.  // initialize your serie (I dont know what you do)
  38.  WaveformGraph1.ClearPlots;
  39.   WaveformGraph1.Plot(thebuffer,f,clRed);
  40. end;
  41.  
  42. end;


« Last Edit: June 10, 2024, 01:49:08 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

 

TinyPortal © 2005-2018