Recent

Author Topic: United OpenLib of Sound (UOS)  (Read 77799 times)

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (U_OS)
« Reply #15 on: November 14, 2012, 11:31:14 am »
Toc, toc, toc, is there anybody here ?  :-[

Please, i need help about thread.start for Windows. (see my earlier post).

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

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: United OpenLib of Sound (U_OS)
« Reply #16 on: November 14, 2012, 12:13:10 pm »
You may get more attention if you start a new thread with a descriptive subject in the most relevant forum subsection... People who know about threading may not necessarily be following a forum thread about a sound library..
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (U_OS)
« Reply #17 on: November 14, 2012, 12:29:59 pm »
@ BigChimp : OK Chef, goed idee  ;)
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

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (U_OS)
« Reply #18 on: November 14, 2012, 07:08:38 pm »
@ BigChimp : it was a great idea, thanks to KpjComp i have the solution  ;D

Yaououuu, i may think to other things...

Here the working new release :
http://fredvs.github.io/uos/
Here the new code :

Code: [Select]
unit U_OS;

{*******************************************************************************
*                  United Openlibraries of Sound ( U_OS )                      *
*                  --------------------------------------                      *
*                                                                              *
*           United procedures to access Open Sound libraries                   *
*                                                                              *
*                                                                              *
*        Lazarus Forum / Fred van Stappen /  Fiens@hotmail.com                 *
*                                                                              *
*             Many thanks to KpjComp, Blaazen, BigChimp                        *                                                                              *
********************************************************************************
*        second realease     first changes:  2012-07-20                        *
*                            second changes: 2012-07-31                        *
*                            3 th changes: 2012-11-13                          *
*                            4 th changes: 2012-11-14                          *
*******************************************************************************}

interface

uses

  Classes, Forms, SysUtils, dialogs ,LazDyn_PortAudio, LazDyn_LibSndFile, LazDyn_Mpg123;


const
  ///// error
  noError            = 0;
  FilePAError        = 10;
  LoadPAError        = 11;
  FileSFError        = 20;
  LoadSFError        = 21;
  FileMPError        = 30;
  LoadMPError        = 31;

  //////// UOS_load() flag
  LoadAll            = 0;   // load all PortAudio + SndFile + MPG123
  LoadPA             = 1;   // load only PortAudio
  LoadSF             = 2;   // load only SndFile
  LoadMP             = 3;   // load only MPG123
  LoadPA_SF          = 4;   // load only PortAudio + SndFile
  LoadPA_MP          = 5;   // load only PortAudio + MPG123
  LoadSF_MP          = 6;   // load only SndFile + MPG123

  Samplerate_root    = 0;

type

  TUOSThread = class(TThread)
  private

  protected
    procedure Execute; override;
  public
   constructor Create(CreateSuspended: boolean);

  end;


type
   TLoadResult = record
    PAloadERROR          : shortint;
    SFloadERROR          : shortint;
    MPloadERROR          : shortint;
    PAinitError          : integer;
    MPinitError          : integer;
   end;



type
    TStreaminfo= record
    streamname        : string;
    Stream               : PPaStream;
    thread               : TUOSThread;
    StreamisOpen         : boolean ;
    DEVICE               : integer ;
    LATENCY              : integer ;
    OutputParameters     : PaStreamParameters;
    handle            : pointer;
    SFopenError       : shortint;
    MPopenError       : shortint;
    SFoutbuf          : array [0..2047]  of byte  ;
    MPoutbuf          : array [0..2047]  of byte  ;
    {$IFDEF Win32}
    BufFrames         : cardinal;
    OutFrames         : cardinal;
     {$else}
    BufFrames       : Tsf_count_t;
    OutFrames       : Tsf_count_t;

     {$endif}
    Filename          : string;
    Status            : shortint;  //// stop = 0, play = 1, pause = 2
    channels          : integer;
    format            : integer;
    frames            : integer;
    samplerateroot    : integer;
    samplerate        : integer;
    sections          : integer;
    seekable          : integer;
    encoding          : integer;
    title             : string;
    copyright         : string;
    software          : string;
    artist            : string;
    comment           : string;
    date              : string;
    tag               : array[0..2] of Char;   (**< Always the string "TAG", the classic intro. *)
    album             : string;  (**< Album string. *)
    genre             : byte;    (**< Genre index. *)

     end;


  var
   UOSLoadFlag         : shortint ;
   UOSLoadResult       : TLoadResult;
   UOSDefOut           : PaDeviceIndex;
   UOSDEVinfo          : PPaDeviceInfo;
   UOSAPIinfo          : PPaHostApiInfo;
   UOSSTREAM            : array   of  Tstreaminfo;
   UOSSTREAMNUM       : integer;
procedure UOS_Load(PA_FileName,SF_FileName,MP_FileName : AnsiString ; flag : shortint );  /////////// dynamic load libraries

procedure UOS_UnLoad() ;

procedure UOS_Init()  ; ////// init libraries

procedure UOS_CreateStream(Soundfile:ansistring;UOS_STREAMNAME:string; SAMPLERATE:integer ; DEVICE:integer ; CHANNELS :integer; LATENCY:integer; SAMPLEFORMAT : string) ;
       ////////////// at Samplerate ( -1 is samplerate of Soundfile) ,
       /////////////   with device ( -1 is default device )
       //////////////// with number of channels (-1 = channels of soundfile, 2 = stereo, -)
        /////////////   at latency  ( -1 is latency suggested ) )
        ///////////// with sampleformat : int8 or int16 or int24 or int32 or float32
        //////////// example : UOS_CreateStream('/home/user/test.mp3','testStream',-1,-1,-1,-1,'int16');

procedure UOS_Play(UOS_STREAMNAME:string) ;   ////// or resume if song was paused

procedure UOS_Stop(UOS_STREAMNAME:string) ;

procedure UOS_Pause(UOS_STREAMNAME:string) ;

//procedure UOS_Position() ;                  //   to do ....


implementation

procedure UOS_Stop(UOS_STREAMNAME:string) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
   UOSSTREAM[x].status := 0 ;
  exit;
  end;
   x := x + 1   ;
  end;

end;

procedure UOS_Pause(UOS_STREAMNAME:string) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
    UOSSTREAM[x].Status := 2 ;
  exit;
  end;
   x := x + 1   ;
  end;

end;



procedure UOS_CreateStream(Soundfile:ansistring;UOS_STREAMNAME:string; SAMPLERATE:integer ; DEVICE:integer ; CHANNELS :integer; LATENCY:integer; SAMPLEFORMAT : string) ;   /// sampleformat : int8 or int16 or int24 or int32 or float32
var
 x, x2, err : integer ;
  sfInfo      : TSF_INFO;
begin
    if not fileexists(Soundfile) then  MessageDlg (Soundfile + ' do not exists...', mtWarning,[mbYes],0)  else
  begin

 x2 := 0 ;
err := -1 ;
   while (x2 < ( Length(UOSSTREAM)) ) and (err <> 1) do begin

 if  UOSSTREAM[x2].streamname =  UOS_STREAMNAME   then
  begin


   if  UOSSTREAM[x2].StreamisOpen = true then
    begin
    UOSSTREAM[x2].status := 0 ;

    sleep(100) ; /////// < buffers need time to release (on some systems) !!!!
      end;

  err := 1  ;
  x := x2;
  end;
   x2 := x2 + 1
  end;

   x2 := 0 ;

 if err = -1 then
  while ( x2 < Length(UOSSTREAM)) and (err <> 2) do begin

 if  (UOSSTREAM[x2].streamname = '')  then
 begin
 UOSSTREAM[x2].streamname:= UOS_STREAMNAME  ;
  UOSSTREAM[x2].status := 0 ;
   UOSSTREAM[x2].StreamisOpen := false ;
 x := x2 ;
  err := 2 ;
  end;
 x2 := x2+1 ;
end;

 if err = -1 then

 begin
 SetLength(UOSSTREAM,  Length(UOSSTREAM) + 1)  ;
 UOSSTREAM[Length(UOSSTREAM)-1].streamname:= UOS_STREAMNAME  ;
  err := 0 ;
 x :=  Length(UOSSTREAM)-1 ;
  UOSSTREAM[x].StreamisOpen := false ;
   UOSSTREAM[x].status := 0 ;
end;


 if err <> -1 then begin
   if  UOSSTREAM[x].StreamisOpen = false then begin

     if device = -1 then
    UOSSTREAM[x].OutputParameters.Device := UOSDefOut else
     UOSSTREAM[x].OutputParameters.Device :=  DEVICE;


if SAMPLEFORMAT = 'int8' then

 UOSSTREAM[x].OutputParameters.SampleFormat :=  paint8 else
 if SAMPLEFORMAT = 'int16' then

 UOSSTREAM[x].OutputParameters.SampleFormat :=  paint16 else
 if SAMPLEFORMAT = 'int32' then

 UOSSTREAM[x].OutputParameters.SampleFormat :=  paint32 else
 if SAMPLEFORMAT = 'float32' then

 UOSSTREAM[x].OutputParameters.SampleFormat :=  pafloat32 else
  UOSSTREAM[x].OutputParameters.SampleFormat :=  paint16  ;


     if LATENCY = -1 then
    UOSSTREAM[x].OutputParameters.SuggestedLatency :=
      (Pa_GetDeviceInfo(  UOSSTREAM[x].OutputParameters.device)^.defaultHighOutputLatency) * 1
      else UOSSTREAM[x].OutputParameters.SuggestedLatency := Latency;


     UOSSTREAM[x].OutputParameters.HostApiSpecificStreamInfo := nil;

     UOSSTREAM[x].StreamisOpen := false ;

     end;
 end;

 ////////////////////////////

         err := -1;

  UOSSTREAM[x].MPopenError := - 1;
  UOSSTREAM[x].SFOpenError := - 1;
    if (UOSloadresult.SFloadERROR = 0) and ((UOSloadflag = LoadAll) or (UOSloadflag = LoadSF)  or (UOSloadflag = LoadPA_SF) or
    (UOSloadflag = LoadSF_MP)) then begin

   UOSSTREAM[x].handle := sf_open(pchar(Soundfile),SFM_READ,sfInfo) ; (* try to open the file *)

   If UOSSTREAM[x].handle  = NIL then
       begin
       UOSSTREAM[x].SFOpenError := 1 ;
       end
       else
        begin
            UOSSTREAM[x].SFOpenError := 0;
            UOSSTREAM[x].filename := Soundfile ;
            UOSSTREAM[x].channels := SFinfo.channels;
            UOSSTREAM[x].format := SFinfo.format;
            UOSSTREAM[x].frames := SFinfo.frames;
            UOSSTREAM[x].samplerate := SFinfo.samplerate;
            UOSSTREAM[x].samplerateroot := SFinfo.samplerate;
            UOSSTREAM[x].sections := SFinfo.sections;
            UOSSTREAM[x].seekable := SFinfo.seekable;
            UOSSTREAM[x].copyright:= sf_get_string(UOSSTREAM[x].handle,SF_STR_COPYRIGHT);
            UOSSTREAM[x].software:= sf_get_string(UOSSTREAM[x].handle,SF_STR_SOFTWARE);
            UOSSTREAM[x].comment:= sf_get_string(UOSSTREAM[x].handle,SF_STR_COMMENT);
            UOSSTREAM[x].date   := sf_get_string(UOSSTREAM[x].handle,SF_STR_DATE);
            UOSSTREAM[x].BufFrames:= length(UOSSTREAM[x].SFoutbuf)   ;
            err := 0;
       end;

    end;


 if ((UOSSTREAM[x].SFOpenError  = 1) or (UOSSTREAM[x].SFOpenError  = -1)) and (UOSLoadresult.MPloadERROR = 0)
 and  ((UOSloadflag = LoadAll) or (UOSloadflag = LoadMP)  or (UOSloadflag = LoadPA_MP) or
    (UOSloadflag = LoadSF_MP)) then begin

       Err := -1;
 UOSSTREAM[x].handle := mpg123_new( NIL, Err);

  if Err = 0 then mpg123_open(UOSSTREAM[x].handle,pchar(Soundfile))

  else UOSSTREAM[x].MPOpenError := 1 ;
  if Err = 0 then Err := mpg123_getformat( UOSSTREAM[x].handle, UOSSTREAM[x].samplerate , UOSSTREAM[x].channels, UOSSTREAM[x].encoding) ;
  if Err = 0 then  begin

    UOSSTREAM[x].MPOpenError := 0;
    UOSSTREAM[x].filename := Soundfile ;
    UOSSTREAM[x].samplerateroot := UOSSTREAM[x].samplerate;
    UOSSTREAM[x].BufFrames:= length(UOSSTREAM[x].MPoutbuf)   ;

  end else UOSSTREAM[x].MPOpenError := 2 ;

    end;
   if err <> 0 then begin

   MessageDlg ('Cannot Open ' + Soundfile + '...', mtWarning,[mbYes],0)  ;
   exit;
   end
   else  begin

    UOSSTREAM[x].streamname   := UOS_STREAMNAME ;
    UOSSTREAM[x].status := 0;
    UOSSTREAM[x].StreamisOpen := false;

    UOSSTREAM[x].OutFrames := 0;
      if CHANNELS = -1 then UOSSTREAM[x].OutputParameters.channelCount:= UOSSTREAM[x].channels
  else  UOSSTREAM[x].OutputParameters.channelCount:= CHANNELS;

    if SAMPLERATE = -1 then
    Pa_OpenStream(@UOSSTREAM[x].Stream, nil, @UOSSTREAM[x].OutputParameters, UOSSTREAM[x].samplerate ,
      64, paClipOff, nil,nil)
      else  Pa_OpenStream(@UOSSTREAM[x].Stream, nil, @UOSSTREAM[x].OutputParameters,SAMPLERATE ,
      64, paClipOff, nil,nil)  ;

    ////////////////
       UOSSTREAM[x].Thread := TUOSThread.Create(True); // With the True parameter it doesn't start automatically

    sleep(10);

        if Assigned(UOSSTREAM[x].Thread.FatalException) then
  raise UOSSTREAM[x].Thread.FatalException;

  end;

   end;

 end;



/////////////////////


 procedure TUOSThread.Execute;

  VAR
  x ,   err  : integer  ;

  begin
    x := UOSSTREAMNUM ;

 if  (UOSSTREAM[x].status = 1) and (UOSSTREAM[x].StreamisOpen = false) then
 begin
  UOSSTREAM[x].StreamisOpen := true;
 Pa_StartStream(UOSSTREAM[X].stream) ;

 ////////////////////////////////////////////////////
  repeat

  if (UOSSTREAM[x].Status = 1) and (UOSSTREAM[x].handle <> nil)  then
 begin

   if UOSSTREAM[x].SFOpenError = 0 then
   begin
 UOSSTREAM[x].OutFrames:= sf_read_short(UOSSTREAM[x].handle, @UOSSTREAM[x].SFoutbuf[0], UOSSTREAM[x].BufFrames  ) ;
   if  (UOSSTREAM[x].OutFrames < UOSSTREAM[x].BufFrames) then UOSSTREAM[x].status := 0;
    end
   else if UOSSTREAM[x].MPOpenError = 0 then
   begin
  mpg123_read( UOSSTREAM[x].handle, @UOSSTREAM[x].MPoutbuf[0], UOSSTREAM[x].BufFrames, UOSSTREAM[x].OutFrames ) ;
   if  (UOSSTREAM[x].OutFrames < UOSSTREAM[x].BufFrames) then UOSSTREAM[x].status := 0;
     end;



    if (UOSSTREAM[x].Status = 1) and (UOSSTREAM[x].handle <> nil)  then
 begin
    if UOSSTREAM[x].SFOpenError = 0 then
   begin
   Pa_WriteStream( UOSSTREAM[x].Stream,@UOSSTREAM[x].SFoutbuf[0],Length(UOSstream[x].SFoutbuf) div 2) ;
   end
     else if UOSSTREAM[x].MPOpenError = 0 then
   begin
   Pa_WriteStream( UOSSTREAM[x].Stream,@UOSSTREAM[x].MPoutbuf[0],Length(UOSstream[x].MPoutbuf) div 4) ;
   end;

   end ;
   end;


   if UOSSTREAM[x].Status = 2 then
   begin
   sleep(100);
   end;

    err := 0;

   if UOSSTREAM[x].Status = 0 then err := 1   ;
 until  (err = 1);

     end;

if(err = 1) then

 begin

   Pa_StopStream(UOSSTREAM[x].Stream);
    Pa_CloseStream(UOSSTREAM[x].Stream);
    UOSSTREAM[x].StreamisOpen := false  ;
     if UOSSTREAM[x].SFOpenError = 0 then sf_close(UOSSTREAM[x].handle);
   if UOSSTREAM[x].MPOpenError = 0 then mpg123_close(UOSSTREAM[x].handle);
   UOSSTREAM[x].thread.Terminate;

  end;

  end;


 ////////////////////////////////////////////////////////////////////////////////////



procedure UOS_Play(UOS_STREAMNAME:string) ;
var
 x : integer ;

begin
 x := 0 ;

   while (x < ( Length(UOSSTREAM)) )  do begin


 if(UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin

   UOSSTREAM[x].Status := 1 ;
   UOSSTREAMNUM := x ;
   UOSSTREAM[x].Thread.Start;


    exit ;
  end;
   x := x + 1   ;
  end;

end;

////////////////////////////////////////////////////////////////////
procedure UOS_Unload() ;

 begin

  Sf_Unload();
  Mp_Unload();
  Pa_Unload();

 end;
///////////////////////////////////////////////////////////////////////////////
 procedure UOS_Init() ;

 begin

    if (UOSLoadResult.MPloadERROR = 0) and ((UOSloadflag = LoadAll) or (UOSloadflag = LoadMP)  or (UOSloadflag = LoadPA_MP) or
    (UOSloadflag = LoadSF_MP)) then if mpg123_init()=MPG123_OK  then  UOSLoadResult.MPinitError := 0 else UOSLoadResult.MPinitError := 1;


  IF (UOSLoadResult.PAloadERROR = 0) and ((UOSloadflag = LoadAll) or (UOSloadflag = LoadPA) or
  (UOSloadflag = LoadPA_SF) or (UOSloadflag = LoadPA_MP)) Then begin
    UOSLoadResult.PAinitError := Pa_Initialize();

      if UOSLoadResult.PAinitError = 0 then begin
    UOSDefOut := Pa_GetDefaultOutputDevice();
    UOSDEVinfo:= Pa_GetDeviceInfo(UOSDefOut);
    UOSAPIinfo:= Pa_GetHostApiInfo(UOSDEVinfo^.hostApi);
     end;

  end;

   end;

procedure UOS_Load( PA_FileName,SF_FileName,MP_FileName : AnsiString ; flag : shortint ) ;

begin

 UOSloadflag := flag ;

   case flag of

    LoadAll : begin

   if not fileexists(PA_FileName) then UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then UOSLoadResult.PAloadERROR:= 0 else UOSLoadResult.PAloadERROR:= 2 ;

  if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
    if  Sf_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

   if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  mp_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;

    end;

     LoadPA : begin

    if not fileexists(PA_FileName) then  UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then  UOSLoadResult.PAloadERROR:= 0  else UOSLoadResult.PAloadERROR:= 2 ;

    end;

    LoadSF : begin

  if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
  if  Sf_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

    end;

     LoadMP : begin

    if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  mp_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;

    end;

   LoadPA_SF : begin

    if not fileexists(PA_FileName) then  UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then  UOSLoadResult.PAloadERROR:= 0  else UOSLoadResult.PAloadERROR:= 2 ;

  if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
    if  Sf_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

     end;

   LoadPA_MP : begin
     if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  MP_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;


    if not fileexists(PA_FileName) then  UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then  UOSLoadResult.PAloadERROR:= 0  else UOSLoadResult.PAloadERROR:= 2 ;


    end;

    LoadSF_MP : begin

   if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
    if  SF_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

   if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  mp_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;

    end;
    end;
    end;

  constructor TUOSThread.Create(CreateSuspended: boolean);
begin
  FreeOnTerminate := True;
  inherited Create(CreateSuspended);
end;

 initialization

  SetLength(UOSSTREAM, 1) ;
 UOSLoadResult.PAloadERROR := -1 ;
 UOSLoadResult.SFloadERROR := -1 ;
 UOSLoadResult.MPloadERROR := -1 ;
 UOSLoadResult.PAinitError := -1 ;
 UOSLoadResult.MPinitError := -1 ;

end.
« Last Edit: May 16, 2013, 03:23:04 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

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: United OpenLib of Sound (U_OS)
« Reply #19 on: November 14, 2012, 10:16:55 pm »
@ BigChimp : it was a great idea, thanks to KpjComp i have the solution  ;D
Tres bien, Chef, je suis heureux que ca marche ;)
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (U_OS)
« Reply #20 on: November 27, 2012, 01:21:40 pm »
Hello everybody.  ;)

Here is the new release of UOS. Included Binary Lib 32/64 + wav, ogg, flac and mp3 samples. Example with multi-streams as well.
http://fredvs.github.io/uos/
All the basic procedures to play a song (wav, ogg, flac, mp3,...) are there :
Play, Pause, Resume, Stop, Volume, Reverse Play, Position, Seek,...

This is the procedural release, next step is to convert it into Class Oop...



Here is the code : Because of limitation of characters, here is first part of the code, next part is in next topic (Thread.execute)
Code: [Select]
unit U_OS;
{*******************************************************************************
*                  United Openlibraries of Sound ( UOS )                       *
*                  --------------------------------------                      *
*                                                                              *
*           United procedures to access Open Sound libraries                   *
*                                                                              *
*      Created by KpjComp, Blaazen, BigChimp, Lazarus forum, FredvS...         *
*                                                                              *
*                 Fred van Stappen /  Fiens@hotmail.com                        *
*                                                                              *
*                                                                              *
********************************************************************************
*        first changes:  2012-07-20   (first shot)                             *
*        second changes: 2012-07-31   (mono thread, only one stream)           *
*        3 th changes: 2012-11-13  (mono thread, multi streams)                *
*        4 th changes: 2012-11-14  (multi threads, multi streams)              *
*        5 th changes: 2012-11-27 (event pause, position, volume, reverse)     *
********************************************************************************}
interface
uses
Classes, ctypes, SysUtils, dialogs ,LazDyn_PortAudio, LazDyn_LibSndFile, LazDyn_Mpg123;
const
  ///// load error
  noError            = 0;
  FilePAError        = 10;
  LoadPAError        = 11;
  FileSFError        = 20;
  LoadSFError        = 21;
  FileMPError        = 30;
  LoadMPError        = 31;
  //////// UOS_load() flag
  LoadAll            = 0;   // load all PortAudio + SndFile + MPG123
  LoadPA             = 1;   // load only PortAudio
  LoadSF             = 2;   // load only SndFile
  LoadMP             = 3;   // load only MPG123
  LoadPA_SF          = 4;   // load only PortAudio + SndFile
  LoadPA_MP          = 5;   // load only PortAudio + MPG123
  LoadSF_MP          = 6;   // load only SndFile + MPG123
  Samplerate_root    = 0;

type
TUOSThread = class(TThread)
 protected
   evPause:PRTLEvent;  // for pausing
   procedure Execute; override;
 public
   constructor Create(CreateSuspended: Boolean; const StackSize: SizeUInt = DefaultStackSize);
   destructor Destroy; override;
 end;

type
   TLoadResult = record
    PAloadERROR          : shortint;
    SFloadERROR          : shortint;
    MPloadERROR          : shortint;
    PAinitError          : integer;
    MPinitError          : integer;
   end;

type
    TStreaminfo= record
    streamname        : string;
    Stream               : PPaStream;
    thread               : TUOSThread;
    StreamisOpen         : boolean ;
    DEVICE               : integer ;
    LATENCY              : integer ;
    OutputParameters     : PaStreamParameters;
    handle            : pointer;
    LibOpenError       : shortint;  //// -1 = nothing open, 0 = SndFile is open, 1 = Mpg123 is is open
    Filename          : string;
    Status            : shortint;  //// stop = 0, play = 1, pause = 2
    channels          : integer;
    volume            : double;
    pan               : double;
    reverse           : boolean;
    format            : integer;
    frames            : Tsf_count_t;
    samplerateroot    : integer;
    samplerate        : integer;
    sections          : integer;
    seekable          : integer;
    encoding          : integer;
    title             : string;
    copyright         : string;
    software          : string;
    artist            : string;
    comment           : string;
    date              : string;
    tag               : array[0..2] of Char;   (**< Always the string "TAG", the classic intro. *)
    album             : string;  (**< Album string. *)
    genre             : byte;    (**< Genre index. *)
    length           : integer;     ///////  in sample ;
    position         : integer;
    sleep            : integer;
    end;
  var
   UOSLoadFlag         : shortint ;
   UOSLoadResult       : TLoadResult;
   UOSDefOut           : PaDeviceIndex;
   UOSDEVinfo          : PPaDeviceInfo;
   UOSAPIinfo          : PPaHostApiInfo;
   UOSSTREAM            : array   of  Tstreaminfo;
   UOSSTREAMNUM       : integer;
   UOSBuzy             : Shortint  ;
procedure UOS_Load(PA_FileName,SF_FileName,MP_FileName : AnsiString ; flag : shortint );  /////////// dynamic load libraries

procedure UOS_UnLoad() ; ///// unload libraries

procedure UOS_Init()  ; ////// init libraries

procedure UOS_CreateStream(Soundfile:ansistring;UOS_STREAMNAME:string; SAMPLERATE:integer ; DEVICE:integer ; CHANNELS :integer; LATENCY:integer; SAMPLEFORMAT : string) ;
       ////////////// at Samplerate ( -1 is samplerate of Soundfile) ,
       /////////////   with device ( -1 is default device )
       //////////////// with number of channels (-1 = channels of soundfile, 2 = stereo, 1 = mono)
        /////////////   at latency  ( -1 is latency suggested ) )
        ///////////// with sampleformat : int8 or int16 or int24 or int32 or float32
        //////////// example : UOS_CreateStream('/home/username/test.mp3','testStream',-1,-1,-1,-1,'int16');

procedure UOS_Play(UOS_STREAMNAME:string) ;   ////// play or resume if song was paused

procedure UOS_Stop(UOS_STREAMNAME:string) ;    ///// stop playing and free thread

procedure UOS_Pause(UOS_STREAMNAME:string) ;   ///// pause playing

procedure UOS_Resume(UOS_STREAMNAME:string) ;  ///// resume playing

function  UOS_Length(UOS_STREAMNAME:string) :  Tsf_count_t;     //// number of samles

function  UOS_Position(UOS_STREAMNAME:string) :  Tsf_count_t;   ///// the position from begining

function  UOS_Status(UOS_STREAMNAME:string) :  shortint;   ///// the status of song ( 0 : Stooped, 1 : playing, 2: paused)

procedure UOS_Seek(UOS_STREAMNAME:string;pos:Tsf_count_t) ;                //// change position

procedure UOS_Volume(UOS_STREAMNAME:string;vol:double)  ;                   ////   change volume ...

procedure UOS_Reverse(UOS_STREAMNAME:string;rev:boolean)  ;
implementation

procedure UOS_Stop(UOS_STREAMNAME:string) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
   UOSSTREAM[x].status := 0 ;
  exit;
  end;
   inc(x) ;
  end;
end;

procedure UOS_Resume(UOS_STREAMNAME:string) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
 UOSSTREAM[x].status := 1 ;
    RTLeventSetEvent(UOSSTREAM[x].thread.evPause)   ;
  exit;
  end;
   inc(x) ;
  end;
end;

procedure UOS_Reverse(UOS_STREAMNAME:string;rev:boolean) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
 UOSSTREAM[x].reverse := rev ;
    exit;
  end;
   inc(x) ;
  end;
end;

procedure  UOS_Seek(UOS_STREAMNAME:string;pos:Tsf_count_t) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
  if (UOSSTREAM[x].LibOpenError = 0)  then sf_seek  (UOSSTREAM[x].handle,pos,SEEK_SET) ;
  if (UOSSTREAM[x].LibOpenError = 1)  then  mpg123_seek  (UOSSTREAM[x].handle,pos,SEEK_SET) ;
  exit;
  end;
   inc(x) ;
  end;
end;

function  UOS_Length(UOS_STREAMNAME:string) :  Tsf_count_t;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
   result := UOSSTREAM[x].length;
    exit;
  end;
   inc(x) ;
  end;
end;


function  UOS_Status(UOS_STREAMNAME:string) :  shortint;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
   result := UOSSTREAM[x].status;
    exit;
  end;
   inc(x) ;
  end;
end;

function  UOS_Position(UOS_STREAMNAME:string) :  Tsf_count_t;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
   result := UOSSTREAM[x].position;
       exit;
  end;
   inc(x) ;
  end;
end;

procedure UOS_Pause(UOS_STREAMNAME:string) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
    RTLeventResetEvent(UOSSTREAM[x].thread.evPause);
  UOSSTREAM[x].Status := 2 ;
  exit;
  end;
   inc(x) ;
  end;
end;

procedure UOS_Volume(UOS_STREAMNAME:string;vol:double)  ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if (UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
  UOSSTREAM[x].volume:= vol;
 case UOSSTREAM[x].LibOpenError of
   1 : mpg123_volume(UOSSTREAM[x].handle,vol);
   end ;
  exit;
  end;
   inc(x) ;
  end;
end;

procedure UOS_CreateStream(Soundfile:ansistring;UOS_STREAMNAME:string; SAMPLERATE:integer ; DEVICE:integer ; CHANNELS :integer; LATENCY:integer; SAMPLEFORMAT : string) ;   /// sampleformat : int8 or int16 or int24 or int32 or float32
var
 x, x2, err : integer ;
  sfInfo      : TSF_INFO;
  mpinfo      : Tmpg123_frameinfo;
  mpid3v1      : Tmpg123_id3v1  ;
 // mpid3v2      : Tmpg123_id3v2  ;   //// to do
begin
  if  UOSBuzy = 0 then begin
  if not fileexists(Soundfile) then  MessageDlg (Soundfile + ' do not exists...', mtWarning,[mbYes],0)  else
  begin
  UOSBuzy := 1 ;
 x2 := 0 ;
err := -1 ;
   while (x2 < ( Length(UOSSTREAM)) ) and (err <> 1) do begin
 if  UOSSTREAM[x2].streamname =  UOS_STREAMNAME   then
  begin
   if  UOSSTREAM[x2].StreamisOpen = true then
    begin
    UOSSTREAM[x2].status := 0 ;
         sleep(100) ; /////// < buffers need time to release (on some systems) !!!!
       end;
   err := 1  ;
  x := x2;
  end;
   inc(x2) ;
  end;
    x2 := 0 ;
 if err = -1 then
  while ( x2 < Length(UOSSTREAM)) and (err <> 2) do begin
 if  (UOSSTREAM[x2].streamname = '')  then
 begin
 UOSSTREAM[x2].streamname:= UOS_STREAMNAME  ;
  UOSSTREAM[x2].status := 0 ;
   UOSSTREAM[x2].StreamisOpen := false ;
 x := x2 ;
  err := 2 ;
  end;
 inc(x2) ;
end;
 if err = -1 then
 begin
 SetLength(UOSSTREAM,  Length(UOSSTREAM) + 1)  ;
 UOSSTREAM[Length(UOSSTREAM)-1].streamname:= UOS_STREAMNAME  ;
  err := 0 ;
 x :=  Length(UOSSTREAM)-1 ;
  UOSSTREAM[x].StreamisOpen := false ;
   UOSSTREAM[x].status := 0 ;
end;
 if err <> -1 then begin
   if  UOSSTREAM[x].StreamisOpen = false then begin
     if device = -1 then
    UOSSTREAM[x].OutputParameters.Device := UOSDefOut else
     UOSSTREAM[x].OutputParameters.Device :=  DEVICE;
    UOSSTREAM[x].OutputParameters.SampleFormat :=  paint16  ;
case SAMPLEFORMAT of
 'int8' : UOSSTREAM[x].OutputParameters.SampleFormat :=  paint8 ;
 'int16' : UOSSTREAM[x].OutputParameters.SampleFormat :=  paint16;
 'int32' : UOSSTREAM[x].OutputParameters.SampleFormat :=  paint32;
 'float32' : UOSSTREAM[x].OutputParameters.SampleFormat :=  pafloat32 ;
 end;
      if LATENCY = -1 then
    UOSSTREAM[x].OutputParameters.SuggestedLatency :=
      (Pa_GetDeviceInfo(  UOSSTREAM[x].OutputParameters.device)^.defaultHighOutputLatency) * 1
      else UOSSTREAM[x].OutputParameters.SuggestedLatency := Latency;
      UOSSTREAM[x].OutputParameters.HostApiSpecificStreamInfo := nil;
      UOSSTREAM[x].StreamisOpen := false ;
      end;
 end;
        err := -1;
  UOSSTREAM[x].LibOpenError := - 1;
    if (UOSloadresult.SFloadERROR = 0) and ((UOSloadflag = LoadAll) or (UOSloadflag = LoadSF)  or (UOSloadflag = LoadPA_SF) or
    (UOSloadflag = LoadSF_MP)) then begin
    /////////////////// try to load stream with Sndfile
     UOSSTREAM[x].handle := sf_open(pchar(Soundfile),SFM_READ,sfInfo) ; (* try to open the file *)
   If UOSSTREAM[x].handle  = NIL then
       else
        begin
            UOSSTREAM[x].LibOpenError := 0;
            UOSSTREAM[x].filename := Soundfile ;
            UOSSTREAM[x].channels := SFinfo.channels;
            UOSSTREAM[x].format := SFinfo.format;
            UOSSTREAM[x].frames := SFinfo.frames;
            UOSSTREAM[x].samplerate := SFinfo.samplerate;
            UOSSTREAM[x].samplerateroot := SFinfo.samplerate;
            UOSSTREAM[x].sections := SFinfo.sections;
            UOSSTREAM[x].seekable := SFinfo.seekable;
            UOSSTREAM[x].copyright:= sf_get_string(UOSSTREAM[x].handle,SF_STR_COPYRIGHT);
            UOSSTREAM[x].software:= sf_get_string(UOSSTREAM[x].handle,SF_STR_SOFTWARE);
            UOSSTREAM[x].comment:= sf_get_string(UOSSTREAM[x].handle,SF_STR_COMMENT);
            UOSSTREAM[x].date   := sf_get_string(UOSSTREAM[x].handle,SF_STR_DATE);
            UOSSTREAM[x].length  :=  sf_Seek(UOSSTREAM[x].handle,0,SEEK_END);
            sf_seek(UOSSTREAM[x].handle,0,SEEK_SET);
            err := 0;
       end;
     end;
     /////////////////// try to load stream with MPG123
  if  (UOSSTREAM[x].LibOpenError  = -1) and (UOSLoadresult.MPloadERROR = 0)
 and  ((UOSloadflag = LoadAll) or (UOSloadflag = LoadMP)  or (UOSloadflag = LoadPA_MP) or
    (UOSloadflag = LoadSF_MP)) then begin
        Err := -1;
 UOSSTREAM[x].handle := mpg123_new( NIL, Err);
   if Err = 0 then
  begin
  mpg123_open(UOSSTREAM[x].handle,pchar(Soundfile))  ;
  Err := mpg123_getformat( UOSSTREAM[x].handle, UOSSTREAM[x].samplerate , UOSSTREAM[x].channels, UOSSTREAM[x].encoding) ;
 end;
      if Err = 0 then  begin
     mpg123_info(UOSSTREAM[x].handle,MPinfo);
      mpg123_id3(UOSSTREAM[x].handle,@mpid3v1,nil);  ////////////// to do : add id2v2
    UOSSTREAM[x].title := trim(mpid3v1.title);
    UOSSTREAM[x].artist := mpid3v1.artist;
  UOSSTREAM[x].album := mpid3v1.album;
 UOSSTREAM[x].date := mpid3v1.year;
 UOSSTREAM[x].comment := mpid3v1.comment;
  UOSSTREAM[x].tag := mpid3v1.tag;
  UOSSTREAM[x].genre := mpid3v1.genre;
    UOSSTREAM[x].length :=  mpg123_length(UOSSTREAM[x].handle);
         UOSSTREAM[x].format := MPinfo.layer;
            UOSSTREAM[x].frames := MPinfo.framesize;
            UOSSTREAM[x].samplerate := MPinfo.rate;
           UOSSTREAM[x].samplerateroot := MPinfo.rate;
         UOSSTREAM[x].length :=   mpg123_length(UOSSTREAM[x].handle);
       UOSSTREAM[x].LibOpenError := 1;
    UOSSTREAM[x].filename := Soundfile ;
   end ;
     end;
  //////////////// here for future others libs
  ///// Welcome to other OpenLibs....
  //////////////
    if Err = -1 then begin

   MessageDlg ('Cannot Open ' + Soundfile + '...', mtWarning,[mbYes],0)  ;
   exit;
   end
   else  begin
     UOSSTREAM[x].streamname   := UOS_STREAMNAME ;
    UOSSTREAM[x].status := 0;
    UOSSTREAM[x].StreamisOpen := false;
    UOSSTREAM[x].volume := 1;
       if CHANNELS = -1 then UOSSTREAM[x].OutputParameters.channelCount:= UOSSTREAM[x].channels
  else  UOSSTREAM[x].OutputParameters.channelCount:= CHANNELS;
     if SAMPLERATE = -1 then
    Pa_OpenStream(@UOSSTREAM[x].Stream, nil, @UOSSTREAM[x].OutputParameters, UOSSTREAM[x].samplerate ,
      64, paClipOff, nil,nil)
      else  Pa_OpenStream(@UOSSTREAM[x].Stream, nil, @UOSSTREAM[x].OutputParameters,SAMPLERATE ,
      64, paClipOff, nil,nil)  ;
     ////////////////
    UOSSTREAM[x].reverse := false;
       UOSSTREAM[x].Thread := TUOSThread.Create(false); // With the True parameter it start automatically
         if Assigned(UOSSTREAM[x].Thread.FatalException) then
  raise UOSSTREAM[x].Thread.FatalException;
   end;
   UOSBuzy := 0 ;
   end;
  end;
  end;
 
« Last Edit: May 16, 2013, 03:23:29 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

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (U_OS)
« Reply #21 on: November 27, 2012, 01:23:44 pm »
... second part of code (see topic before).

Code: [Select]
/////////////////////
  procedure TUOSThread.execute;
   VAR
  x , x2  : integer  ;
  outbuf            :  array[0..$ffff] of cInt16;
  {$IFDEF Win32}
    wantframes         : cardinal;
    OutFrames         : cardinal;
     {$else}
    wantframes       : Tsf_count_t;
    OutFrames       : Tsf_count_t;
      {$endif}
   type
  TShortIntArray = array[0..$ffff] of cInt16;
  PShortIntArray = ^TShortIntArray;
var
  pp:PShortIntArray;
  begin
    x := UOSSTREAMNUM ;

 if  (UOSSTREAM[x].status = 1) and ( UOSSTREAM[x].StreamisOpen = false) then
 begin
  Pa_StartStream(UOSSTREAM[X].stream) ;
     UOSSTREAM[x].StreamisOpen := true;
       UOSSTREAM[X].position:=0;
    wantframes :=   length(outbuf) div UOSSTREAM[x].Channels;
   ////////////////////////////////////////////////////
   if (UOSSTREAM[x].reverse = true) and (UOSSTREAM[x].LibOpenError = 0)  then sf_seek  (UOSSTREAM[x].handle,-1,SEEK_END) ;
  if (UOSSTREAM[x].reverse = true) and (UOSSTREAM[x].LibOpenError = 1)  then  mpg123_seek  (UOSSTREAM[x].handle,0,SEEK_END) ;
   //////////////////////////////////////
  repeat
  if  (UOSSTREAM[x].handle <> nil)  then begin
      RTLeventWaitFor(evPause);
      RTLeventSetEvent(evPause);
  case  UOSSTREAM[x].Status of
  1 : begin
  case UOSSTREAM[x].LibOpenError of
   0 : begin
    //////////// reverse
  if UOSSTREAM[x].reverse = true then   if sf_seek  (UOSSTREAM[x].handle, -  wantframes ,SEEK_CUR) > 0 then else UOSSTREAM[x].status := 0;
  //////////////////
      UOSSTREAM[X].position:= sf_seek(UOSSTREAM[x].handle, 0 ,SEEK_CUR);
 if UOSSTREAM[x].status > 0  then  OutFrames:= sf_read_short(UOSSTREAM[x].handle, @outbuf[0], wantframes  ) ;
      RTLeventWaitFor(evPause);
      RTLeventSetEvent(evPause);
    if UOSSTREAM[x].Status = 1 then begin
   if  (OutFrames < Wantframes ) then UOSSTREAM[x].status := 0 else
   begin
    ///////////////reverse
 if UOSSTREAM[x].reverse = true then begin
     pp := @outbuf[0];
      x2 := 0 ;
      for x2 := 0 to (Outframes-1) do
      pp^[x2] := NtoLE(round(LEtoN(pp^[Outframes-x2-1])));
      end;
    ///////////////
    if UOSSTREAM[x].volume <> 1 then
    begin
      pp := @outbuf[0];
      x2 := 0 ;
    for x2 := 0 to (Outframes*UOSSTREAM[x].Channels)-1 do
      pp^[x2] := NtoLE(round(LEtoN(pp^[x2])*UOSSTREAM[x].volume));
     end;
     RTLeventWaitFor(evPause);
      RTLeventSetEvent(evPause);
  if UOSSTREAM[x].Status = 1 then Pa_WriteStream( UOSSTREAM[x].Stream,@outbuf[0],outframes div 2) ;
   end ;
   end;
    end;
1 : begin
      //////////// reverse
  if UOSSTREAM[x].reverse = true then   if mpg123_seek  (UOSSTREAM[x].handle, - wantframes div 2,SEEK_CUR) > 0 then else UOSSTREAM[x].status := 0;
  //////////////////
   UOSSTREAM[X].position:= mpg123_tell(UOSSTREAM[x].handle) ;
  mpg123_read( UOSSTREAM[x].handle, @outbuf[0], wantframes , outframes ) ;
    RTLeventWaitFor(evPause);
      RTLeventSetEvent(evPause);
      ///////////  reverse
    if UOSSTREAM[x].reverse = true then begin
    pp := @outbuf[0];
    x2 := 0 ;
   for x2 := 0 to (Outframes div 2)-1  do
   pp^[x2] := NtoLE(round(LEtoN(pp^[(Outframes div 2)-x2-1])));
   end;
      ///////////
 if UOSSTREAM[x].Status = 1 then   if  (OutFrames < wantframes) then UOSSTREAM[x].status := 0 else
  Pa_WriteStream( UOSSTREAM[x].Stream,@outbuf[0],outframes div 4) ;
       end;
       end ;
     end;
  end;
 end;
 until  UOSSTREAM[x].Status = 0;
     end;
if UOSSTREAM[x].Status = 0 then
 begin
   Pa_StopStream(UOSSTREAM[x].Stream);
    Pa_CloseStream(UOSSTREAM[x].Stream);
    UOSSTREAM[x].StreamisOpen := false  ;
      case UOSSTREAM[x].LibOpenError of
   0 : sf_close(UOSSTREAM[x].handle);
   1 : mpg123_close(UOSSTREAM[x].handle);
   end;
    UOSSTREAM[x].thread.Terminate;
   end;
   end;

procedure UOS_Play(UOS_STREAMNAME:string) ;
var
 x : integer ;
begin
 x := 0 ;
   while (x < ( Length(UOSSTREAM)) )  do begin
 if(UOSSTREAM[x].streamname =  UOS_STREAMNAME)    then
  begin
     UOSSTREAMNUM := x ;
   UOSSTREAM[x].Status := 1 ;
     RTLeventSetEvent( UOSSTREAM[x].thread.evPause)  ;
      exit ;
  end;
   inc(x) ;
  end;
end;

procedure UOS_Unload() ;
  begin
   Sf_Unload();
  Mp_Unload();
  Pa_Unload();
  end;
 procedure UOS_Init() ;
 begin
    if (UOSLoadResult.MPloadERROR = 0) and ((UOSloadflag = LoadAll) or (UOSloadflag = LoadMP)  or (UOSloadflag = LoadPA_MP) or
    (UOSloadflag = LoadSF_MP)) then if mpg123_init()=MPG123_OK  then  UOSLoadResult.MPinitError := 0 else UOSLoadResult.MPinitError := 1;
   IF (UOSLoadResult.PAloadERROR = 0) and ((UOSloadflag = LoadAll) or (UOSloadflag = LoadPA) or
  (UOSloadflag = LoadPA_SF) or (UOSloadflag = LoadPA_MP)) Then begin
    UOSLoadResult.PAinitError := Pa_Initialize();
      if UOSLoadResult.PAinitError = 0 then begin
    UOSDefOut := Pa_GetDefaultOutputDevice();
    UOSDEVinfo:= Pa_GetDeviceInfo(UOSDefOut);
    UOSAPIinfo:= Pa_GetHostApiInfo(UOSDEVinfo^.hostApi);
     end;
    end;
     end;

procedure UOS_Load( PA_FileName,SF_FileName,MP_FileName : AnsiString ; flag : shortint ) ;
begin
 UOSloadflag := flag ;
   case flag of
    LoadAll : begin
   if not fileexists(PA_FileName) then UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then UOSLoadResult.PAloadERROR:= 0 else UOSLoadResult.PAloadERROR:= 2 ;

     if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
    if  Sf_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

   if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  mp_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;

    end;

     LoadPA : begin

    if not fileexists(PA_FileName) then  UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then  UOSLoadResult.PAloadERROR:= 0  else UOSLoadResult.PAloadERROR:= 2 ;

    end;

    LoadSF : begin

  if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
  if  Sf_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

    end;

     LoadMP : begin

    if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  mp_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;

    end;

   LoadPA_SF : begin

    if not fileexists(PA_FileName) then  UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then  UOSLoadResult.PAloadERROR:= 0  else UOSLoadResult.PAloadERROR:= 2 ;

  if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
    if  Sf_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

     end;

   LoadPA_MP : begin
     if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  MP_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;


    if not fileexists(PA_FileName) then  UOSLoadResult.PAloadERROR:= 1   else
     if  Pa_Load (PA_FileName) then  UOSLoadResult.PAloadERROR:= 0  else UOSLoadResult.PAloadERROR:= 2 ;


    end;

    LoadSF_MP : begin

   if not fileexists(SF_FileName) then UOSLoadResult.SFloadERROR:= 1 else
    if  SF_Load (SF_FileName)  then UOSLoadResult.SFloadERROR:= 0 else UOSLoadResult.SFloadERROR:= 2 ;

   if not fileexists(MP_FileName) then UOSLoadResult.MPloadERROR := 1 else
    if  mp_Load (Mp_FileName)  then UOSLoadResult.MPloadERROR := 0 else UOSLoadResult.MPloadERROR := 2 ;

    end;
    end;
    end;

 constructor TUOSThread.Create(CreateSuspended: Boolean;
  const StackSize: SizeUInt);
begin
  inherited Create(CreateSuspended,StackSize);
  evPause:=RTLEventCreate;
end;

destructor TUOSThread.Destroy;
begin
   RTLeventdestroy(evPause);
  inherited Destroy;
end;

 initialization
   SetLength(UOSSTREAM, 1) ;
 UOSLoadResult.PAloadERROR := -1 ;
 UOSLoadResult.SFloadERROR := -1 ;
 UOSLoadResult.MPloadERROR := -1 ;
 UOSLoadResult.PAinitError := -1 ;
 UOSLoadResult.MPinitError := -1 ;
   UOSBuzy := 0;
end.                                                                         
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

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (UOS)
« Reply #22 on: January 06, 2013, 03:10:56 pm »
Hello everybody  :D

Im very happy to release the new version of UOS.
UOS comes to class and is more OOP now.

Here is the new release of UOS. Included Binary Lib 32/64 + wav, ogg, flac and mp3 samples. Example with multi-streams and DSP procedure as well.
http://fredvs.github.io/uos/

All of your remarks are very welcome.
Here first part of code (the rest follows in next topic):

Code: [Select]
unit uos;

{*******************************************************************************
*                  United Openlibraries of Sound ( UOS )                       *
*                  --------------------------------------                      *
*                                                                              *
*          United procedures to access Open Sound (IN/OUT) libraries           *
*                                                                              *
*              With Big contributions of (in alphabetic order)                 *
*  BigChimp, Blaazen, FredvS, KpjComp, Leledumbo,  Lazarus forum,...           *
*                                                                              *
*                 Fred van Stappen /  Fiens@hotmail.com                        *
*                                                                              *
*                                                                              *
********************************************************************************
*        first changes:  2012-07-20   (first shot)                             *
*        second changes: 2012-07-31   (mono thread, only one stream)           *
*        3 th changes: 2012-11-13  (mono thread, multi streams)                *
*        4 th changes: 2012-11-14  (multi threads, multi streams)              *
*        5 th changes: 2012-11-27 (event pause, position, volume, reverse)     *
*        6 th changes: 2012-12-31 (Class/Oop look, DSP, multi IN/OUT)          *
********************************************************************************}

interface

uses
  Classes, ctypes, SysUtils, Dialogs, LazDyn_PortAudio, LazDyn_LibSndFile, LazDyn_Mpg123;

type
  TArFloat = array[0..$ffff] of cfloat  ;
  TArShort = array[0..$ffff] of cInt16;
  TArLong  = array[0..$ffff] of cInt32;
  PArFloat = ^TArFloat;
  PArShort = ^TArShort;
  PArLong  = ^TArLong;
  TProc = Function(HandleIn:pointer; Inbuf: TArFloat ;param1:double; param2:double; format:shortint; position:longint; libused:shortint) :  TArFloat;

const
  ///// error
  noError = 0;
  FilePAError = 10;
  LoadPAError = 11;
  FileSFError = 20;
  LoadSFError = 21;
  FileMPError = 30;
  LoadMPError = 31;
  //////// UOS_load() flag
  LoadAll = 0;   // load all PortAudio + SndFile + MPG123
  LoadPA = 1;   // load only PortAudio
  LoadSF = 2;   // load only SndFile
  LoadMP = 3;   // load only MPG123
  LoadPA_SF = 4;   // load only PortAudio + SndFile
  LoadPA_MP = 5;   // load only PortAudio + MPG123
  LoadSF_MP = 6;   // load only SndFile + MPG123
 
type
  TUOS_LoadResult = record
    PAloadError: shortint;
    SFloadError: shortint;
    MPloadError: shortint;
    PAinitError: integer;
    MPinitError: integer;
  end;

type
  TUOS_Init = class(TObject)
  public
    PA_FileName: ansistring;
    SF_FileName: ansistring;
    MP_FileName: ansistring;
    flag: shortint;     ////// Default is 0 : load all ;
    LoadResult: TUOS_LoadResult;
    DefOut: PaDeviceIndex;
    DEVinfo: PPaDeviceInfo;
    APIinfo: PPaHostApiInfo;
    constructor Create;
    procedure LoadLib;
    procedure InitLib;
    procedure UnloadLib;
  end;

  type
  TUOS_InStream  = class;
  TUOS_OutStream = class;
  TUOS_Player    = class(TThread)
  protected
    evPause: PRTLEvent;  // for pausing
    procedure Execute; override;
    public
    Enabled: boolean;
    status: shortint;
    EndProc: procedure ;
    StreamIn:  array of TUOS_InStream;
    StreamOut: array of TUOS_OutStream;
    constructor Create(CreateSuspended: boolean;const StackSize: SizeUInt = DefaultStackSize);
    procedure Prepare;                  ///// prepare everything before play
    procedure Play;                     //// play the thread
    procedure Stop;                    ///// stop playing and free thread
    procedure Pause;                  ///// pause playing
    procedure Seek(InName: string;pos: Tsf_count_t);  //// change position

    procedure AddOutput(OutName: string; Device: integer; Latency: integer; SampleRate: integer; SampleFormat: shortint); ////// Add a Output
    //////////// OutName : name of new Output,
    //////////// Device ( -1 is default device )
    //////////// Latency  ( -1 is latency suggested ) )
    //////////// SampleRate : delault : -1 (44100)
    //////////// SampleFormat : -1 default : Int16 : (0: Float32, 1:Int32, 2:Int16)
                                       //      warning if Mpg123 is used set please to 2: Int16 ( only Int16 is working now)
    //////////// example : AddOutput('Output1',-1,-1,-1,-1);

    procedure AddFromFile(InName: string; Filename: string; OutName: string; SampleFormat : shortint);/////// Add a audio file into input
    ////////// InName : name of new input
    ////////// FileName : filename of audio file
    ////////// OutName : name of existing Output // (if multi-output then OutName = name of each output separeted by ';')
    //////////// SampleFormat : -1 default : Int16 : for SndFile (0: Float32, 1:Int32, 2:Int16)
                                               //  : for Mpg123  ( only Int16 is working now, all other SampleFormat will be set to Int16)
    //////////// example : AddFromFile('input1',edit5.Text,'output1',-1)

    function InputLength(InName: string) : longint ; /////// Lenght of Input in samples
    ////////// InName : name of existing input
   
    function InputPosition(InName: string) : longint ;  ////// actual postion of sample
    ////////// InName : name of existing input

    procedure AddDSPin(DSPName:string; InName: string; BeforeProc:TProc; AfterProc:TProc);   ///// add a DSP procedure for input
    ////////// DSPName : name of new DSP
    ////////// InName : name of existing input
    ////////// BeforeProc : procedure to do before the buffer is filled
    ////////// AfterProc : procedure to do after the buffer is filled
    ////////// example : AddDSPIn('DSPReverse','Input1',@beforereverse,@afterreverse);
   
    procedure SetDSPin(DSPName:string; InName: string; Enable: boolean; BefProcParam1: Double; BefProcParam2: Double ; //// change value of DSP
                               AftProcParam1: Double ;  AftProcParam2: Double);
     ////////// DSPName : name of existing DSP
     ////////// InName : name of existing input
     ////////// Enable :  DSP enabled
     ////////// BefProcParam1 : parameter1 of beforeProc
     ////////// BefProcParam2 : parameter2 of beforeProc
     ////////// AftProcParam1 : parameter1 of afterProc
     ////////// AftProcParam2 : parameter2 of afterProc
     ////////// example : SetDSPIn('DSPVolume','Input1',True,0,0,0.6,0);

     procedure AddDSPout(DSPName:string; OutName: string; BeforeProc:TProc; AfterProc:TProc);  //// usefull if multi output
    ////////// OutName : name of output
    ////////// BeforeProc : procedure to do before the buffer is filled
    ////////// AfterProc : procedure to do after the buffer is filled just before to give to output
    ////////// example : AddDSPout('DSPvolumeOut','Output1',@volumeproc,nil);

    destructor Destroy; override;
  end;

  type
  TUOS_DSP = class(TObject)
   public
    Name: string;
    Enabled: boolean;
    PHandleSt : pointer;
    BefProc: TProc;     //// Procedure to load before buffer is filled
    BefProcParam1: double;  //// parameter 1 of BefProc procedure
    BefProcParam2: double;  //// parameter 2 of BefProc procedure
    AftProc: TProc ;  //// Procedure to load after buffer is filled
    AftProcParam1: double; 
    AftProcParam2: double;
    end;
 
  type
  TUOS_InInfo = record
    Position: longint;
    Poseek : longint;
    Status: shortint;
    Isopen: boolean;
     {$if defined(cpu64)}
    Wantframes: Tsf_count_t;
    OutFrames: Tsf_count_t;
     {$else}
    Wantframes: longint;
    OutFrames: longint;
     {$endif}
    typeIn: shortint;  ////// -1 : nothing, 0 : from audio file, 1 : from other stream, 2 : from input
    Filename: string;  //// if typeIn = 0
    Title: string;
    Samplerateroot: integer;
    Samplerate: integer;
    SampleFormat : shortint;
    Copyright: string;
    Software: string;
    Artist: string;
    Comment: string;
    Date: string;
    Tag: array[0..2] of char;  (**< Always the string "TAG", the classic intro. *)
    Album: string;  (**< Album string. *)
    Genre: byte;    (**< Genre index. *)
    Format: integer;
    Frames: Tsf_count_t;
    Sections: integer;
    Encoding: integer;
    Seekable: integer;
    Lengthst: integer;     ///////  in sample ;
    Channels: integer;
    LibOpen: shortint;    //// -1 : nothing open, 0 : sndfile open, 1 : mpg123 open
    externalstream: TUOS_InStream;   //// if if typeIn = 1
    inputnum: integer; ////// if typeIn = 2  >>>> num of input device
    ratio : shortint;  ////// for output : if mpg123 then ratio := 2
  end;

type
  TUOS_InStream = class(TObject)
   public
    Enabled: boolean;
    Name: string;
    Info: TUOS_InInfo;
    HandleSt: pointer;
    InBuffer : TArFloat ;
    DSP: array of TUOS_DSP ;
    Output : string;
    destructor Destroy; override;
    end;

type
  TUOS_OutStream = class(TObject)
   public
    Enabled: boolean;
    Name: string;
    Info: PaStreamParameters;
    HandleSt: pointer;
    OutBuffer : TArFloat;
    SampleRate : integer;
    SampleFormat : shortint;
    DSP: array of TUOS_DSP ;
    destructor Destroy; override;
   end;

var
  UOSLoadFlag: shortint;
  UOSLoadResult: TUOS_LoadResult;
  UOSDefOut: PaDeviceIndex;
  UOSDEVinfo: PPaDeviceInfo;
  UOSAPIinfo: PPaHostApiInfo;

implementation

procedure TUOS_Player.Prepare;
var
x : integer;
begin
   for x := 0 to  high(StreamOut)  do  if StreamOut[x].HandleSt <> nil then
         Pa_StartStream(StreamOut[x].HandleSt);
  start;
   RTLeventResetEvent(evPause);
  Status := 2;
  Enabled := True;
  if Assigned(FatalException) then raise FatalException;
end;

procedure TUOS_Player.Play;
begin
  if Enabled = True then
  begin
    Status := 1;
    RTLeventSetEvent(evPause);
  end;
end;

procedure TUOS_Player.Stop;
begin
  if Enabled = True then
  begin
    RTLeventSetEvent(evPause);
    Status := 0;
  end;
end;

procedure TUOS_Player.Pause;
begin
  if Enabled = True then
  begin
    RTLeventResetEvent(evPause);
    Status := 2;
  end;
end;

procedure TUOS_Player.Seek(InName: string;pos: Tsf_count_t);  //// change position
var
  x : integer;
begin
     for x := 0 to  high(StreamIn)  do  if StreamIn[x].Name = InName then
      StreamIn[x].Info.Poseek:=pos;
   end;

function TUOS_Player.InputPosition(InName: string) : longint ;
var
  x : integer;
begin
  result :=  0 ;
   for x := 0 to  high(StreamIn) do  if StreamIn[x].Name = InName then
   result := StreamIn[x].info.Position;
  end;

function TUOS_Player.InputLength(InName: string) : longint ;
var
  x : integer;
begin
  result :=  0 ;
   for x := 0 to  high(StreamIn) do  if StreamIn[x].Name = InName then
   result := StreamIn[x].info.Lengthst;
  end;

procedure TUOS_Player.SetDSPin(DSPName:string; InName: string; Enable: boolean; BefProcParam1: Double; BefProcParam2: Double ;
  AftProcParam1: Double ;  AftProcParam2: Double);
var
  x,y  : integer;
begin
  for x := 0 to  high(StreamIn)  do  if StreamIn[x].Name = InName then
       if (Length(StreamIn[x].DSP)) > 0 then
    for y:= 0 to  high(StreamIn[x].DSP)  do  if (StreamIn[x].DSP[y].Name = DSPName) then
    begin
      StreamIn[x].DSP[y].Enabled := Enable;
     StreamIn[x].DSP[y].BefProcParam1:= BefProcParam1;
     StreamIn[x].DSP[y].BefProcParam2:= BefProcParam2;
     StreamIn[x].DSP[y].AftProcParam1:= AftProcParam1;
     StreamIn[x].DSP[y].AftProcParam2:= AftProcParam2;
       end;
  end;

procedure TUOS_Player.AddDSPin(DSPName:string;InName: string; BeforeProc: TProc; AfterProc: TProc);
var
  x,y, err  : integer;
begin
  err := -1 ;
    for x := 0 to  high(StreamIn)  do  if StreamIn[x].Name = InName then
    begin
      if (Length(StreamIn[x].DSP)) > 0 then
     for y:= 0 to  high(StreamIn[x].DSP)  do  if (StreamIn[x].DSP[y].Name = DSPName) or (StreamIn[x].DSP[y].Name = '') then
     begin
      err := 0 ;
       StreamIn[x].DSP[y].Name := DSPName;
      StreamIn[x].DSP[y].BefProc:= BeforeProc;
       StreamIn[x].DSP[y].AftProc:= AfterProc;
       StreamIn[x].DSP[y].Enabled:=true;
       end;
      end;
      if err = -1 then
    begin
    SetLength(StreamIn[x].DSP, Length(StreamIn[x].DSP) + 1);
    StreamIn[x].DSP[Length(StreamIn[x].DSP) - 1] := TUOS_DSP.Create;
    StreamIn[x].DSP[Length(StreamIn[x].DSP) - 1].Name := DSPName;
    StreamIn[x].DSP[Length(StreamIn[x].DSP) - 1].BefProc:= BeforeProc;
    StreamIn[x].DSP[Length(StreamIn[x].DSP) - 1].AftProc:= AfterProc;
    StreamIn[x].DSP[Length(StreamIn[x].DSP) - 1].Enabled:=true;
  end;
   end;

procedure TUOS_Player.AddDSPout(DSPName:string;OutName: string; BeforeProc: TProc; AfterProc: TProc);
var
  x,y, err  : integer;
begin
  err := -1 ;
    for x := 0 to  high(StreamOut)  do  if StreamOut[x].Name = OutName then
    begin
      if (Length(StreamOut[x].DSP)) > 0 then
     for y:= 0 to  high(StreamOut[x].DSP) do  if (StreamOut[x].DSP[y].Name = DSPName) or (StreamOut[x].DSP[y].Name = '') then
     begin
      err := 0 ;
      StreamOut[x].DSP[y].BefProc:= BeforeProc;
      StreamOut[x].DSP[y].AftProc:= AfterProc;
      StreamOut[x].DSP[y].Enabled:=true;
      end;
      end;
      if err = -1 then
    begin
    SetLength(StreamOut[x].DSP, Length(StreamOut[x].DSP) + 1);
    StreamOut[x].DSP[Length(StreamOut[x].DSP) - 1] := TUOS_DSP.Create;
    StreamOut[x].DSP[Length(StreamOut[x].DSP) - 1].Name := DSPName;
    StreamOut[x].DSP[Length(StreamOut[x].DSP) - 1].BefProc:= BeforeProc;
    StreamOut[x].DSP[Length(StreamOut[x].DSP) - 1].AftProc:= AfterProc;
    StreamOut[x].DSP[Length(StreamOut[x].DSP) - 1].Enabled:=true;
  end;
   end;

procedure TUOS_Player.AddOutput(OutName: string; Device: integer; Latency: integer; SampleRate: integer; SampleFormat: shortint);
    //////////// OutName : name of new Output,
    //////////// Device ( -1 is default device )
    //////////// Latency  ( -1 is latency suggested ) )
    //////////// SampleRate : delault : -1 (44100)
    //////////// SampleFormat : -1 default : Int16  for SndFile (0: Float32, 1:Int32, 2:Int16)
                                              //    for Mpg123  (2: Int16 working)  (0: Float32, 1:Int32 not working now)
    //////////// example : AddOutput('Output1',-1,-1,-1,-1);
var
  x, err : integer;
  begin
  x := 0;
  err := -1;
  while (x < (Length(StreamOut))) and (err <> 1) do
  begin
    if StreamOut[x].Name = OutName then
    begin
       if (StreamOut[x].HandleSt <> nil) then
      begin
        Pa_StopStream(StreamOut[x].HandleSt);
        Pa_CloseStream(StreamOut[x].HandleSt);
      end;
      err := 0;
      end;
   if err <> 0 then Inc(x);
  end;

  if err = -1 then  begin
     x := 0;
    while (x < Length(StreamOut)) and (err <> 0) do
    begin
      if (StreamOut[x].Name = '') then
      begin
        StreamOut[x].Name := OutName;
        err := 0;
      end;
      if err <> 0 then Inc(x);
    end;
    end;

  if err = -1 then
  begin
    SetLength(StreamOut, Length(StreamOut) + 1);
    StreamOut[Length(StreamOut) - 1] := TUOS_OutStream.Create;
    StreamOut[Length(StreamOut) - 1].Name := OutName;
    err := 0;
    x := Length(StreamOut) - 1;
  end;

  if err > -1 then
  begin
   StreamOut[x].info.HostApiSpecificStreamInfo := nil;
   if device = -1 then StreamOut[x].info.device := Pa_GetDefaultOutputDevice()
  else StreamOut[x].info.device := device;

  if SampleRate = -1 then StreamOut[x].SampleRate := 44100 else StreamOut[x].SampleRate := SampleRate;

  if Latency = -1 then StreamOut[x].info.SuggestedLatency := (Pa_GetDeviceInfo(StreamOut[x].info.device)^.defaultHighOutputLatency) * 1
  else StreamOut[x].info.SuggestedLatency := Latency;

  StreamOut[x].info.SampleFormat := paInt16;
     case SampleFormat of
     0 : StreamOut[x].info.SampleFormat := paFloat32;
     1 : StreamOut[x].info.SampleFormat := paInt32;
     2 : StreamOut[x].info.SampleFormat := paInt16;
    end;
   StreamOut[x].SampleFormat := SampleFormat;

  StreamOut[x].info.channelCount := 2;
  StreamOut[x].Enabled:=true;
 err := Pa_OpenStream(@StreamOut[x].HandleSt, nil, @StreamOut[x].Info, StreamOut[x].SampleRate,64, paClipOff, nil, nil);

  if err <> 0 then MessageDlg(Pa_GetErrorText(err), mtWarning, [mbYes], 0)  ;
end;
  end;

« Last Edit: May 16, 2013, 03:23:55 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

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (UOS)
« Reply #23 on: January 06, 2013, 03:16:08 pm »
Because of limitation of characters, here next part of the code (see earlier topic)

Code: [Select]
procedure TUOS_Player.AddFromFile(InName: string; Filename: string; OutName: string; SampleFormat: shortint);
      ////////// InName : name of new input
      ////////// FileName : filename of audio file
      ////////// OutName : name of existing Output // (if multi-output then OutName = name of each output separeted by ';')
      ////////// SampleFormat : -1 default : Int16 (0: Float32, 1:Int32, 2:Int16)
      ////////// example : AddFromFile('Input1','/usr/home/test.ogg','Output1;Output2',-1);
var
  x, err: integer;
  sfInfo: TSF_INFO;
  mpinfo: Tmpg123_frameinfo;
  mpid3v1: Tmpg123_id3v1;
begin
   if not fileexists(FileName) then MessageDlg(FileName + ' do not exists...', mtWarning, [mbYes], 0)
    else
  begin
    x := 0;
    err := -1;

    while (x < (Length(StreamIn))) and (err <> 0) do
    begin
        if (StreamIn[x].Name = InName)  then  ////// seeking for same Input
            begin
            if (StreamIn[x].HandleSt <> nil) then
           case StreamIn[x].info.LibOpen of
          0: sf_close(StreamIn[x].HandleSt);
          1: mpg123_close(StreamIn[x].HandleSt);
        end;
         err := 0;
        end;
       if err <> 0 then inc(x);
    end;

    if err = -1 then
    begin
      x := 0;
      while (x < Length(StreamIn))  and (err <> 0) do      ///// seeking for some empty input
      begin
        if (StreamIn[x].Name = '') then
        begin
          StreamIn[x].Name := InName;
         err := 0;
        end;
       if err <> 0 then Inc(x);
      end;
    end;

    if err = -1 then       ///// creating a new input
    begin
      SetLength(StreamIn, Length(StreamIn) + 1);
      StreamIn[Length(StreamIn) - 1] := TUOS_InStream.Create;
      StreamIn[Length(StreamIn) - 1].Name := InName;
      err := 0;
      x := Length(StreamIn) - 1;
      end;

   if err <> -1 then
    begin
      err := -1;
      StreamIn[x].info.LibOpen := -1;
       StreamIn[x].info.Isopen := False;
      if (UOSloadresult.SFloadERROR = 0) and
        ((UOSloadflag = LoadAll) or (UOSloadflag = LoadSF) or
        (UOSloadflag = LoadPA_SF) or (UOSloadflag = LoadSF_MP)) then
      begin
        StreamIn[x].HandleSt := sf_open(PChar(FileName), SFM_READ, sfInfo);
        (* try to open the file *)
        if StreamIn[x].HandleSt = nil then
        begin
          StreamIn[x].info.LibOpen := -1;
        end
        else
        begin
          StreamIn[x].info.LibOpen := 0;
          StreamIn[x].info.typeIn := 0;
          StreamIn[x].Info.filename := FileName;
          StreamIn[x].Info.channels := SFinfo.channels;
          StreamIn[x].Info.format := SFinfo.format;
          StreamIn[x].Info.frames := SFinfo.frames;
          StreamIn[x].Info.samplerate := SFinfo.samplerate;
          StreamIn[x].Info.samplerateroot := SFinfo.samplerate;
          StreamIn[x].Info.sections := SFinfo.sections;
          StreamIn[x].Info.seekable := SFinfo.seekable;
          StreamIn[x].Info.Wantframes := length(StreamIn[x].InBuffer) div StreamIn[x].Info.Channels;
          StreamIn[x].Info.copyright := sf_get_string(StreamIn[x].HandleSt, SF_STR_COPYRIGHT);
          StreamIn[x].Info.software := sf_get_string(StreamIn[x].HandleSt, SF_STR_SOFTWARE);
          StreamIn[x].Info.comment := sf_get_string(StreamIn[x].HandleSt, SF_STR_COMMENT);
          StreamIn[x].Info.date := sf_get_string(StreamIn[x].HandleSt, SF_STR_DATE);
          StreamIn[x].Info.Lengthst := sf_Seek(StreamIn[x].HandleSt, 0, SEEK_END);
          sf_seek(StreamIn[x].HandleSt, 0, SEEK_SET);
          StreamIn[x].Enabled := False;
          err := 0;
        end;
       end;
      if ((StreamIn[x].info.LibOpen = -1)) and (UOSLoadresult.MPloadERROR = 0) and
        ((UOSloadflag = LoadAll) or (UOSloadflag = LoadMP) or
        (UOSloadflag = LoadPA_MP) or (UOSloadflag = LoadSF_MP)) then
      begin
           Err := -1;
        StreamIn[x].HandleSt := mpg123_new(nil, Err);
       if Err = 0 then begin
          mpg123_open(StreamIn[x].HandleSt, PChar(FileName)) ;
          end
        else
          StreamIn[x].info.LibOpen := -1;
        if Err = 0 then
          Err := mpg123_getformat(StreamIn[x].HandleSt,
            StreamIn[x].info.samplerate, StreamIn[x].info.channels,
            StreamIn[x].info.encoding);
        if Err = 0 then
        begin
          StreamIn[x].info.filename := filename;
          StreamIn[x].Info.Wantframes :=
          length(StreamIn[x].InBuffer) div StreamIn[x].info.channels;
          mpg123_info(StreamIn[x].HandleSt, MPinfo);
          mpg123_id3(StreamIn[x].HandleSt, @mpid3v1, nil);  ////////////// to do : add id2v2
          StreamIn[x].info.title := trim(mpid3v1.title);
          StreamIn[x].info.artist := mpid3v1.artist;
          StreamIn[x].info.album := mpid3v1.album;
          StreamIn[x].info.date := mpid3v1.year;
          StreamIn[x].info.comment := mpid3v1.comment;
          StreamIn[x].info.tag := mpid3v1.tag;
          StreamIn[x].info.genre := mpid3v1.genre;
          StreamIn[x].info.samplerateroot := MPinfo.rate;
          StreamIn[x].info.samplerate := MPinfo.rate;
          StreamIn[x].info.Format := MPinfo.layer;
          StreamIn[x].info.frames := MPinfo.framesize;
          StreamIn[x].info.lengthst := mpg123_length(StreamIn[x].HandleSt);
          StreamIn[x].info.LibOpen := 1;
                end
        else
          StreamIn[x].info.LibOpen := -1;
        end;
      if err <> 0 then
      begin
       MessageDlg('Cannot Open ' + FileName + '...', mtWarning, [mbYes], 0);
        exit;
      end
      else
      begin
        StreamIn[x].Name := InName;
        StreamIn[x].info.Status := 1;
        StreamIn[x].info.isOpen := True;
        StreamIn[x].Enabled := True;
        StreamIn[x].Info.Position := 0;
        StreamIn[x].info.OutFrames := 0;
        StreamIn[x].Output := OutName ;
        StreamIn[x].Info.Poseek := -1 ;
        case StreamIn[x].info.LibOpen of
         0 :
         begin
         StreamIn[x].info.ratio := StreamIn[x].info.Channels;
         if SampleFormat = -1 then  StreamIn[x].info.SampleFormat := 2
       else StreamIn[x].info.SampleFormat := SampleFormat  ;
         end;
         1 :  begin
         StreamIn[x].info.ratio := 2 * StreamIn[x].info.Channels;
           StreamIn[x].info.SampleFormat := 2 ; /////// how to set mpg123 to float ?
           // mpg123_param(StreamIn[x].HandleSt,  2, MPG123_FORCE_FLOAT,0);  ///// do not work
            end;
           end;
            end;
    end;
   end;
end;

procedure TUOS_Player.Execute;
var
 // pf: PArFloat;
  ps: PArShort;
  pl: PArLong;
   x, x2, x3 : integer;
  begin
      repeat
          for x := 0 to  high(StreamIn) do
       begin
      RTLeventWaitFor(evPause);  ///// is there a pause waiting ?
      RTLeventSetEvent(evPause);
     
      if (StreamIn[x].HandleSt <> nil) and (StreamIn[x].info.Status = 1) and
        (StreamIn[x].Enabled = True) then
      begin

        if  StreamIn[x].Info.Poseek > -1 then begin     ////// is there a seek waiting ?
              case StreamIn[x].info.LibOpen of
      0: sf_seek(StreamIn[x].HandleSt, StreamIn[x].Info.Poseek, SEEK_SET);
      1: mpg123_seek(StreamIn[x].HandleSt, StreamIn[x].Info.Poseek, SEEK_SET);
              end;
            StreamIn[x].Info.Poseek := -1 ;
                    end;
         
        StreamIn[x].Info.OutFrames := 0 ;
         
          case StreamIn[x].info.LibOpen of      ///// get current position
          0: StreamIn[x].info.position := sf_seek(StreamIn[x].HandleSt, 0, SEEK_CUR);
          1: StreamIn[x].info.position := mpg123_tell(StreamIn[x].HandleSt);
          end;
         
           //////// DSPin StreamIn[x].DSP[y].BeforeBuffProc
              if  (StreamIn[x].info.Status = 1) and (length(StreamIn[x].DSP) > 0) then
           for x2 := 0 to  high(StreamIn[x].DSP) do
       if (StreamIn[x].DSP[x2].Enabled = true) and  (StreamIn[x].DSP[x2].BefProc <> nil) then
      StreamIn[x].DSP[x2].BefProc(StreamIn[x].HandleSt,StreamIn[x].InBuffer,StreamIn[x].DSP[x2].BefProcParam1,
      StreamIn[x].DSP[x2].BefProcParam2,StreamIn[x].info.SampleFormat,StreamIn[x].info.Position,StreamIn[x].info.LibOpen) ;     
         ///// end DSP BeforeProc 
         
           RTLeventWaitFor(evPause);  ///// is there a pause waiting ?
           RTLeventSetEvent(evPause);
             
        case StreamIn[x].info.LibOpen of   //////////// Here we are, reading the data and store it in buffer
          0: case StreamIn[x].info.SampleFormat of
              0 : StreamIn[x].Info.OutFrames := sf_read_float(StreamIn[x].HandleSt, @StreamIn[x].InBuffer[0],StreamIn[x].info.Wantframes);
              1 : StreamIn[x].Info.OutFrames := sf_read_int(StreamIn[x].HandleSt, @StreamIn[x].InBuffer[0],StreamIn[x].info.Wantframes);
              2 : StreamIn[x].Info.OutFrames := sf_read_short(StreamIn[x].HandleSt, @StreamIn[x].InBuffer[0],StreamIn[x].info.Wantframes);
             end;
          1:  mpg123_read(StreamIn[x].HandleSt, @StreamIn[x].InBuffer[0],StreamIn[x].Info.wantframes, StreamIn[x].Info.outframes);
              /////// To do : allow float32 and int32 for mpg123
        end;
       
              if StreamIn[x].Info.OutFrames < 1 then  StreamIn[x].Info.status := 0;  //////// no more data then close the stream
             
         //////// DSPin AfterBuffProc     
   if  (StreamIn[x].info.Status = 1) and (length(StreamIn[x].DSP) > 0) then
    for x2 := 0 to  high(StreamIn[x].DSP) do
   if (StreamIn[x].DSP[x2].Enabled = true) and  (StreamIn[x].DSP[x2].AftProc <> nil) then
 
     StreamIn[x].InBuffer :=
    StreamIn[x].DSP[x2].AftProc(StreamIn[x].HandleSt,StreamIn[x].InBuffer,StreamIn[x].DSP[x2].AftProcParam1,
    StreamIn[x].DSP[x2].AftProcParam2,StreamIn[x].info.SampleFormat,StreamIn[x].info.Position,StreamIn[x].info.LibOpen) ;     
        ///// End DSPin AftterBuffProc

      end;
      end;  ////////
          ////////////////// Seeking if InStream is terminated
    if status > 0 then
   begin
      status := 0 ;
   for x := 0 to  high(StreamIn) do if(StreamIn[x].HandleSt <> nil) and (StreamIn[x].info.Status = 1) then  status := 1;
   end;

    //////////////////////// Give Buffer to Output
      RTLeventWaitFor(evPause);
      RTLeventSetEvent(evPause);

        if status = 1 then  for x := 0 to  high(StreamOut) do 

           if (StreamOut[x].HandleSt <> nil) and (StreamOut[x].Enabled = True) then
           begin
           for x2 :=  0 to high(StreamOut[x].outBuffer) do StreamOut[x].OutBuffer[x2] := 0;      ////// clear output
           
           for x2 := 0 to  high(StreamIn) do  if (StreamIn[x2].HandleSt <> nil) and (StreamIn[x2].Enabled = True)
          and (pos(StreamOut[x].Name,StreamIn[x2].Output) > 0)   then                 
                              //////// copy buffer-in into buffer-out
          for x3 :=  0 to high(StreamIn[x2].InBuffer)  do StreamOut[x].OutBuffer[x3] := StreamOut[x].OutBuffer[x3] + StreamIn[x2].InBuffer[x3];
       
           //////// DSPOut AfterBuffProc
              if (length(StreamOut[x].DSP) > 0) then
           for x3 := 0 to  high(StreamOut[x].DSP) do
       if (StreamOut[x].DSP[x3].Enabled = true) and  (StreamOut[x].DSP[x3].AftProc <> nil) then
      StreamOut[x].DSP[x3].AftProc(StreamOut[x].HandleSt,StreamOut[x].OutBuffer,StreamOut[x].DSP[x3].AftProcParam1,
      StreamOut[x].DSP[x3].AftProcParam2,StreamOut[x].SampleFormat,-1,-1) ;     
           ///// end DSPOut AfterBuffProc
           
                          ///////// Finally give buffer to output
      Pa_WriteStream(StreamOut[x].HandleSt, @StreamOut[x].OutBuffer[0],StreamIn[x2].Info.outframes div StreamIn[x2].Info.ratio);
 
           
  end;
 
  until status = 0;
   ////////////////////////////////////////////////////////// end of loop

   ////////////////////////// Terminate Thread
     if status = 0 then
     begin
     for x := 0 to  high(StreamOut) do
     if (StreamOut[x].HandleSt <> nil) then
      begin
        Pa_StopStream(StreamOut[x].HandleSt);
        Pa_CloseStream(StreamOut[x].HandleSt);
      end;
     for x := 0 to  high(StreamIn) do
     if (StreamIn[x].HandleSt <> nil) then
         case StreamIn[x].info.LibOpen of
          0: sf_close(StreamIn[x].HandleSt);
          1: mpg123_close(StreamIn[x].HandleSt);
        end;
       if EndProc <> nil then EndProc; /////  Execute EndProc procedure
    Terminate;
  end;
end;

constructor TUOS_Player.Create(CreateSuspended: boolean; const StackSize: SizeUInt);
begin
  inherited Create(CreateSuspended, StackSize);
  FreeOnTerminate := True;
  evPause := RTLEventCreate;
  Enabled := False;
  status := 2;
  setlength(StreamIn, 1);
  setlength(StreamOut, 1);
  StreamIn[0] := TUOS_InStream.Create;
  StreamOut[0] := TUOS_OutStream.Create;
  StreamIn[0].Name := '';
  StreamOut[0].Name := '';
  StreamOut[0].HandleSt := nil;
  StreamIn[0].HandleSt := nil;
 end;

destructor TUOS_Player.Destroy;
var
x : integer;
begin
  RTLeventdestroy(evPause);
   for x := 0 to  high(StreamOut) do  StreamOut[x].Free;
   for x := 0 to  high(StreamIn)  do  StreamIn[x].Free;
       inherited Destroy;
end;

destructor TUOS_InStream.Destroy;
var
x : integer;
begin
   for x := 0 to  high(DSP) do  DSP[x].Free;
  inherited Destroy;
end;

destructor TUOS_OutStream.Destroy;
var
x : integer;
begin
   for x := 0 to  high(DSP) do  DSP[x].Free;
  inherited Destroy;
end;

procedure TUOS_Init.UnLoadLib();
begin
  Sf_Unload();
  Mp_Unload();
  Pa_Unload();
end;

procedure TUOS_Init.InitLib();
begin
  if (LoadResult.MPloadERROR = 0) and ((flag = LoadAll) or (flag = LoadMP) or
    (flag = LoadPA_MP) or (flag = LoadSF_MP)) then
    if mpg123_init() = MPG123_OK then
      LoadResult.MPinitError := 0
    else
      LoadResult.MPinitError := 1;
  if (LoadResult.PAloadERROR = 0) and ((flag = LoadAll) or (flag = LoadPA) or
    (flag = LoadPA_SF) or (flag = LoadPA_MP)) then
  begin
    LoadResult.PAinitError := Pa_Initialize();
    if LoadResult.PAinitError = 0 then
    begin
      DefOut := Pa_GetDefaultOutputDevice();
      DEVinfo := Pa_GetDeviceInfo(DefOut);
      APIinfo := Pa_GetHostApiInfo(DEVinfo^.hostApi);
    end;
  end;
end;

procedure TUOS_Init.LoadLib();
begin
  case flag of
    LoadAll:
    begin
      if not fileexists(PA_FileName) then
        LoadResult.PAloadERROR := 1
      else
      if Pa_Load(PA_FileName) then
        LoadResult.PAloadERROR := 0
      else
        LoadResult.PAloadERROR := 2;
      if not fileexists(SF_FileName) then
        LoadResult.SFloadERROR := 1
      else
      if Sf_Load(SF_FileName) then
        LoadResult.SFloadERROR := 0
      else
        LoadResult.SFloadERROR := 2;
      if not fileexists(MP_FileName) then
        LoadResult.MPloadERROR := 1
      else
      if mp_Load(Mp_FileName) then
        LoadResult.MPloadERROR := 0
      else
        LoadResult.MPloadERROR := 2;
    end;

    LoadPA:
    begin
      if not fileexists(PA_FileName) then
        LoadResult.PAloadERROR := 1
      else
      if Pa_Load(PA_FileName) then
        LoadResult.PAloadERROR := 0
      else
        LoadResult.PAloadERROR := 2;
    end;

    LoadSF:
    begin
      if not fileexists(SF_FileName) then
        LoadResult.SFloadERROR := 1
      else
      if Sf_Load(SF_FileName) then
        LoadResult.SFloadERROR := 0
      else
        LoadResult.SFloadERROR := 2;
    end;

    LoadMP:
    begin
      if not fileexists(MP_FileName) then
        LoadResult.MPloadERROR := 1
      else
      if mp_Load(Mp_FileName) then
        LoadResult.MPloadERROR := 0
      else
        LoadResult.MPloadERROR := 2;
    end;

    LoadPA_SF:
    begin
      if not fileexists(PA_FileName) then
        LoadResult.PAloadERROR := 1
      else
      if Pa_Load(PA_FileName) then
        LoadResult.PAloadERROR := 0
      else
        LoadResult.PAloadERROR := 2;
      if not fileexists(SF_FileName) then
        LoadResult.SFloadERROR := 1
      else
      if Sf_Load(SF_FileName) then
        LoadResult.SFloadERROR := 0
      else
        LoadResult.SFloadERROR := 2;
    end;

    LoadPA_MP:
    begin
      if not fileexists(MP_FileName) then
        LoadResult.MPloadERROR := 1
      else
      if MP_Load(Mp_FileName) then
        LoadResult.MPloadERROR := 0
      else
        LoadResult.MPloadERROR := 2;
      if not fileexists(PA_FileName) then
        LoadResult.PAloadERROR := 1
      else
      if Pa_Load(PA_FileName) then
        LoadResult.PAloadERROR := 0
      else
        LoadResult.PAloadERROR := 2;
    end;

    LoadSF_MP:
    begin
      if not fileexists(SF_FileName) then
        LoadResult.SFloadERROR := 1
      else
      if SF_Load(SF_FileName) then
        LoadResult.SFloadERROR := 0
      else
        LoadResult.SFloadERROR := 2;
      if not fileexists(MP_FileName) then
        LoadResult.MPloadERROR := 1
      else
      if mp_Load(Mp_FileName) then
        LoadResult.MPloadERROR := 0
      else
        LoadResult.MPloadERROR := 2;
    end;
  end;

end;

constructor TUOS_Init.Create;
begin
  flag := 0;
  LoadResult.PAloadERROR := -1;
  LoadResult.SFloadERROR := -1;
  LoadResult.MPloadERROR := -1;
  LoadResult.PAinitError := -1;
  LoadResult.MPinitError := -1;
end;

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

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: United OpenLib of Sound (UOS)
« Reply #24 on: January 06, 2013, 04:16:38 pm »
Indents, the horror! ... Is the structure right with those end; 's?
Code: [Select]
   if  (StreamIn[x].info.Status = 1) and (length(StreamIn[x].DSP) > 0) then
    for x2 := 0 to  high(StreamIn[x].DSP) do
   if (StreamIn[x].DSP[x2].Enabled = true) and  (StreamIn[x].DSP[x2].AftProc <> nil) then
 
     StreamIn[x].InBuffer :=
    StreamIn[x].DSP[x2].AftProc(StreamIn[x].HandleSt,StreamIn[x].InBuffer,StreamIn[x].DSP[x2].AftProcParam1,
    StreamIn[x].DSP[x2].AftProcParam2,StreamIn[x].info.SampleFormat,StreamIn[x].info.Position,StreamIn[x].info.LibOpen) ;     
        ///// End DSPin AftterBuffProc

      end;
      end;  ////////

(We don't do it spamming spacebar  ::)  Select long piece of code, and Ctrl+K+U or Ctrl+K+I)

Also you could attach the code in the forum post, maybe in .zip. I'm sure many will find it easier downloading the code.
« Last Edit: January 06, 2013, 06:06:33 pm by User137 »

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (UOS)
« Reply #25 on: January 06, 2013, 07:26:51 pm »
Quote
Also you could attach the code in the forum post, maybe in .zip. I'm sure many will find it easier downloading the code.

I have given the link  to code because in the zip there is all the  bin libraries for 32/64 bits for Linux, Windows and Mac OSX.
There are also samples oF ogg, wav, flac and mp3 files.

All that zipped is about 3 mega (too much for attachment.)

Here the link with all the code :

http://fredvs.github.io/uos/

EDIT : There is a zipped file in attachment, but it is only uos.pas ..., better to download all the package...


« Last Edit: May 16, 2013, 03:24:27 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

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (UOS)
« Reply #26 on: January 07, 2013, 01:07:39 pm »
Quote
Indents, the horror!

What do you mean ?
If you have a better solution for DSP procedure, you are very welcome to show us your way.
Thanks
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

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: United OpenLib of Sound (UOS)
« Reply #27 on: January 07, 2013, 01:22:42 pm »
Indenting means how you format the text. One guide is here: http://edn.embarcadero.com/article/10280

Example:
Code: [Select]
             if something then
                begin
  DoSomething;
         end;
Versus
Code: [Select]
if something then
begin
  DoSomething;
end;
You must know what i mean? Properly indented code is much more readable.

Dibo

  • Hero Member
  • *****
  • Posts: 1055
Re: United OpenLib of Sound (UOS)
« Reply #28 on: January 07, 2013, 01:32:38 pm »
Maybe Fred vS is using non-standard editor options (like unchecked "Tab on spaces" or something like that). I had similar behavior when I opened java file in Netbeans IDE from Eclipse IDE

Fred vS

  • Hero Member
  • *****
  • Posts: 3500
    • StrumPract is the musicians best friend
Re: United OpenLib of Sound (UOS)
« Reply #29 on: January 07, 2013, 01:34:33 pm »
Quote
You must know what i mean?

Ok, i see now, but... it is the fault of JEDI, i let him do the work for me  :-[

And i agree, the job is NOT well done.
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