Recent

Author Topic: PortAudio for Lazarus under Ubuntu -- Note on Installation  (Read 1982 times)

Curt Carpenter

  • Sr. Member
  • ****
  • Posts: 402
PortAudio for Lazarus under Ubuntu -- Note on Installation
« on: October 01, 2019, 09:05:38 pm »
I'm posting this in the hope that it might save someone interested in using the PortAudio library with Lazarus and Ubuntu some time.

I was having trouble getting PortAudio set up to work with Lazarus under Ubuntu (Linux) but finally found the following at https://askubuntu.com/questions/736238/how-do-i-install-and-setup-the-environment-for-using-portaudio:



The following worked for me on Ubuntu 16.04:

sudo apt-get install libasound-dev portaudio19-dev libportaudio2 libportaudiocpp0
sudo apt-get install ffmpeg libav-tools



I only used the first apt-get line since my application does not need mpeg, and the insall worked for me under Ubuntu 18.04.

I downloaded fpc-portaudio-19.zip from the internet at https://sourceforge.net/projects/humus/files/external/portmedia/ into a folder, uncompressed it and followed the installation instructions in the README file.  With that done, I was finally able to compile and run the two fpc examples in the download. 

The program here translates the testpasine example to run as a Lazarus application.  The application form consists of just a memo (taking the place of the "writelns" in the fpc example) and one button.  The "readln" from the original fpc example has just been deleted.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode delphi}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   PortAudio, CTypes;
  10.  
  11. { TForm1 }
  12.  
  13. type
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Memo1: TMemo;
  17.     procedure Button1Click(Sender: TObject);
  18.   private
  19.     { private declarations }
  20.   public
  21.     procedure Error;
  22.   end;
  23.  
  24. const
  25.   SampleRate = 44100;
  26.   FramesPerBuffer = 64;
  27.   TwoPi = 2*Pi;
  28.  
  29.   // How long you want to play the test sine:
  30.   NumSecs = 1;
  31.  
  32.   // Wavetable size. Influences your pitch:
  33.   TableSize = 200;
  34.  
  35. type
  36.  
  37.   { A type which holds a wavetable, two integers keeping track of
  38.     at which offset in the wavetable each channel is currently
  39.     playing (= phase), and a message: }
  40.  
  41.   PaTestData = record
  42.     Sine : array[0..TableSize] of CFloat;
  43.     LeftPhase : CInt32;
  44.     RightPhase : CInt32;
  45.     AMessage : PChar;
  46.   end;
  47.   PPaTestData = ^PaTestData;
  48.  
  49.  
  50.  
  51. var
  52.   Form1: TForm1;
  53.  
  54.   OutputParameters : PaStreamParameters;
  55.  
  56.   { This pointer points to a pointer which will be returned by
  57.     Pa_OpenStream: }
  58.   Stream : PPaStream;
  59.   Err : PaError;
  60.   Data : PaTestData;
  61.   DataPointer : PPaTestData;
  62.   j : CInt32;
  63.  
  64. implementation
  65.  
  66. {$R *.lfm}
  67.  
  68. { TForm1 }
  69.  
  70. function PaTestCallback( inputBuffer : pointer; OutputBuffer : pointer;
  71.       framesPerBuffer : culong; timeInfo : PPaStreamCallbackTimeInfo;
  72.       statusFlags : PaStreamCallbackFlags; UserData : pointer ) : CInt32;
  73.       cdecl;
  74. var
  75.   OutBuffer : PCFloat;
  76.   i : culong;
  77.   LocalDataPointer : PPaTestData;
  78. begin
  79.   OutBuffer := PCFloat(OutputBuffer);
  80.   LocalDataPointer := PPaTestData(UserData);
  81.  
  82.   // Fill the buffer...
  83.   for i := 0 to (FramesPerBuffer-1) do begin
  84.  
  85.     OutBuffer^ := LocalDataPointer^.Sine[LocalDataPointer^.LeftPhase];
  86.     Inc(OutBuffer);
  87.  
  88.     OutBuffer^ := LocalDataPointer^.Sine[LocalDataPointer^.RightPhase];
  89.     Inc(OutBuffer);
  90.  
  91.     Inc(LocalDataPointer^.LeftPhase);
  92.     if (LocalDataPointer^.LeftPhase >= TableSize ) then
  93.         LocalDataPointer^.LeftPhase :=
  94.           (LocalDataPointer^.LeftPhase - TableSize);
  95.  
  96.     Inc(LocalDataPointer^.RightPhase);
  97.     Inc(LocalDataPointer^.RightPhase);
  98.     if ( LocalDataPointer^.RightPhase >= TableSize ) then
  99.         LocalDataPointer^.RightPhase :=
  100.           (LocalDataPointer^.RightPhase - TableSize);
  101.   end;
  102.  
  103.   PaTestCallback := CInt32(0);
  104. end;
  105.  
  106. { This is called when playback is finished.
  107.   Remember: ALWAYS USE CDECL or your pointers will be messed up!
  108.   Pointers to this function must be castable to PPaStreamFinishedCallback: }
  109.  
  110. procedure StreamFinished( UserData : pointer ); cdecl;
  111. var
  112.   LocalDataPointer : PPaTestData;
  113. begin
  114.   LocalDataPointer := PPaTestData(UserData);
  115. //  Memo1.lines.add('Stream Completed: '+ LocalDataPointer^.AMessage);
  116. end;
  117.  
  118.  
  119. procedure TForm1.Error;
  120. begin
  121.   Pa_Terminate();
  122.   Memo1.lines.add('An error occured while using the portaudio Stream');
  123.   Memo1.lines.add('Error number: '+ IntToStr(Err));
  124.   Memo1.lines.add('Error message: '+ Pa_GetErrorText( Err ) );
  125.   halt;
  126. end;
  127.  
  128. procedure TForm1.Button1Click(Sender: TObject);
  129. begin
  130.   Memo1.lines.add('PortAudio Test: Output Sine wave. SR = ' +
  131.    IntToStr(SampleRate) + ', Buffer size = ' + IntToStr(FramesPerBuffer));
  132.  
  133.   DataPointer := @Data;
  134.  
  135.   // Fill a Sine wavetable (Float Data -1 .. +1)
  136.   for j := 0 to TableSize-1 do begin
  137.     Data.Sine[j] := Sin( j*TwoPi/TableSize);
  138.   end;
  139.   Data.LeftPhase := 0;
  140.   Data.RightPhase := 0;
  141.  
  142.   Err := Pa_Initialize;
  143.   if not Err = 0 then Error;
  144.  
  145.   OutputParameters.Device := Pa_GetDefaultOutputDevice;
  146.   OutputParameters.ChannelCount := CInt32(2);
  147.   OutputParameters.SampleFormat := paFloat32;
  148.   OutputParameters.SuggestedLatency :=
  149.     (Pa_GetDeviceInfo(OutputParameters.device)^.defaultHighOutputLatency)*1;
  150.   OutputParameters.HostApiSpecificStreamInfo := nil;
  151.  
  152.   Memo1.lines.add('Latency '+FloatToStr(
  153.    Pa_GetDeviceInfo(OutputParameters.device)^.defaultHighOutputLatency));
  154.  
  155.   Err := Pa_OpenStream(@Stream, nil, @OutputParameters, SampleRate,
  156.     FramesPerBuffer, paClipOff, PPaStreamCallback(@PaTestCallback),
  157.     DataPointer);
  158.  
  159.   if not Err = 0 then Error;
  160.  
  161.   Data.AMessage := 'No Message'#0;
  162.  
  163.   Err := Pa_SetStreamFinishedCallback(Stream,
  164.     PPaStreamFinishedCallback(@StreamFinished));
  165.   if not Err = 0 then Error;
  166.  
  167.   Memo1.lines.add('Press <RETURN> to attempt start playing a Sine for '+
  168.     IntToStr(NumSecs)+' sec.');
  169.  
  170.   Err := Pa_StartStream( Stream );
  171.   if not Err = 0 then Error;
  172.  
  173.   Memo1.lines.add('Play for '+IntToStr(NumSecs)+ ' seconds.');
  174.   Pa_Sleep( NumSecs * 1000 );
  175.  
  176.   Err := Pa_StopStream( Stream );
  177.   if not Err = 0 then Error;
  178.  
  179.   Err := Pa_CloseStream( Stream );
  180.   if not Err = 0 then Error;
  181.  
  182.   Pa_Terminate;
  183.   Memo1.lines.add('Test finished.');
  184.  
  185. end;
  186.  
  187. end.
  188.  
  189.  
  190.  

Nevada Smith

  • New Member
  • *
  • Posts: 20
Re: PortAudio for Lazarus under Ubuntu -- Note on Installation
« Reply #1 on: December 25, 2019, 07:39:33 am »
It was of great help to me today. Availability of documentation and sample source code for PortAudio+FPC combination is quite rare.

metis

  • Sr. Member
  • ****
  • Posts: 300
Re: PortAudio for Lazarus under Ubuntu -- Note on Installation
« Reply #2 on: December 28, 2019, 02:13:12 pm »
@Nevada Smith

Quote
Availability of documentation and sample source code for PortAudio+FPC combination is quite rare.
Yes, indeed it is, but there are some, e.g.:

> 'Breakout Box': http://breakoutbox.de/pascal/pascal.html
-> GoTo "PortAudio + PortMidi Examples V 0.14".
Those Examples use a Callback-Function and static Linking.
The Code above corresponds to the TestPAsinex-Example (see attached 'TestPAsinex.7z').

> 'UOS' (= United OpenLib of Sound) uses a ReadLoop and dynamic Linking.
There are several Threads about 'UOS' in this Forum, like:
https://forum.lazarus.freepascal.org/index.php/topic,17599.0.html
https://forum.lazarus.freepascal.org/index.php/topic,17521.msg96750.html#msg96750.

If You'd like to enjoy Music and Videos with FPC and cristal-clear Portaudio-Sound, try out 'FFPlay4Laz':
https://forum.lazarus.freepascal.org/index.php/topic,26666.msg337046.html#msg337046
For the Moment, it's all Win32, but it works on Linux with Wine, as shown here:
https://forum.lazarus.freepascal.org/index.php/topic,26666.msg342546.html#msg342546
(Would be interesting for me, if it works with Your Linux-Version, too.)  :)
« Last Edit: December 28, 2019, 02:19:07 pm by metis »
Life could be so easy, if there weren't those f*** Details.
My FFmpeg4Lazarus = FFPlay4Laz + FFGrab4Laz + FFInfo4Laz

 

TinyPortal © 2005-2018