program waveform_fpGUI; {$mode objfpc}{$H+} uses {$IFDEF UNIX} cthreads, {$ENDIF} SysUtils, Classes, fpg_base, fpg_main, fpg_widget, uos_flat, ctypes, fpg_style_chrome_silver_flatmenu, fpg_stylemanager, {%units 'Auto-generated GUI code'} fpg_form, fpg_editbtn, fpg_label, fpg_button {%endunits}; type Twaveform = class(TfpgForm) private {@VFD_HEAD_BEGIN: waveform} FilenameEdit1: TfpgFileNameEdit; Label1: TfpgLabel; Button1: TfpgButton; Custom1: TfpgWidget; {@VFD_HEAD_END: waveform} public procedure AfterCreate; override; procedure drawwave(Sender: TObject); procedure btnDrawClick(Sender: TObject); procedure btnCloseClick(Sender: TObject); procedure DrawWaveForm; end; var opath, fnsf, fnmp, ordir: string; PlayerIndex1, In1Index, filelength, framewanted: integer; poswav, chan: integer; waveformdata: array of cfloat; {@VFD_NEWFORM_DECL} {@VFD_NEWFORM_IMPL} procedure Twaveform.DrawWaveForm; begin waveformdata := uos_InputGetLevelArray(PlayerIndex1, In1Index); fpgapplication.ProcessMessages; button1.tag := 1; custom1.Visible := True; end; procedure Twaveform.btndrawclick(Sender: TObject); begin custom1.Visible := False; windowtitle := 'Wave Form. uos version ' + IntToStr(uos_getversion()); PlayerIndex1 := 0; //// Create the player. uos_CreatePlayer(PlayerIndex1); //// PlayerIndex : from 0 to what your computer can do ! //// If PlayerIndex exists already, it will be overwriten... //// add input from audio file with default parameters In1Index := uos_AddFromFile(PlayerIndex1, PChar(FilenameEdit1.filename)); //// no output because only decode the steam for wave form /// get the length of the audio file filelength := uos_InputLength(PlayerIndex1, In1Index); chan := uos_InputGetChannels(PlayerIndex1, In1Index); // writeln('chan = ' + inttostr(chan)); // writeln('filelength = ' + inttostr(filelength)); ///// set calculation of level/volume into array (usefull for wave form procedure) uos_InputSetLevelArrayEnable(PlayerIndex1, In1Index, 2); ///////// set level calculation (default is 0) // 0 => no calcul // 1 => calcul before all DSP procedures. // 2 => calcul after all DSP procedures. //// determine how much frame will be designed framewanted := filelength div custom1.Width; uos_InputSetFrameCount(PlayerIndex1, In1Index, framewanted); ///// Assign the procedure of object to execute at end of stream uos_EndProc(PlayerIndex1, @DrawWaveForm); uos_Play(PlayerIndex1); /////// everything is ready, here we are, lets do it... end; procedure Twaveform.drawwave(Sender: TObject); begin if button1.tag = 0 then with Custom1 do begin Canvas.GradientFill(GetClientRect, clgreen, clBlack, gdVertical); Canvas.TextColor := clWhite; Canvas.DrawText(60, 20, 'uos'); end else begin Custom1.Canvas.GradientFill(GetClientRect, clwhite, clblack, gdVertical); poswav := 0; while poswav < length(waveformdata) div chan do begin if chan = 2 then begin Custom1.Canvas.setcolor(cldarkgreen); Custom1.Canvas.drawLine(poswav, Custom1.Height div 2, poswav, ((Custom1.Height div 2) - 1) - round( (waveformdata[poswav * 2]) * (Custom1.Height / 2) - 1)); Custom1.Canvas.setcolor(clred); Custom1.Canvas.drawLine(poswav, (Custom1.Height div 2) + 2, poswav, ((Custom1.Height div 2) + 1) + round( (waveformdata[(poswav * 2) + 1]) * (Custom1.Height / 2) + 1)); end; if chan = 1 then begin Custom1.Canvas.setcolor(cldarkgreen); Custom1.Canvas.drawLine(poswav, 0, poswav, ((Custom1.Height) - 1) - round((waveformdata[poswav]) * (Custom1.Height) - 1)); end; Inc(poswav); end; Custom1.Canvas.TextColor := clBlack; Custom1.Canvas.DrawText(60, 20, 'Right Channel'); Custom1.Canvas.TextColor := clWhite; Custom1.Canvas.DrawText(60, Custom1.Height - 40, 'Left Channel'); end; end; procedure Twaveform.btnCloseClick(Sender: TObject); begin uos_UnloadLib(); end; procedure Twaveform.AfterCreate; begin {%region 'Auto-generated GUI code' -fold} {@VFD_BODY_BEGIN: waveform} Name := 'waveform'; SetPosition(267, 185, 841, 475); WindowTitle := 'Wave Form'; IconName := ''; Hint := ''; WindowPosition := wpScreenCenter; BackgroundColor := clmoneygreen; Ondestroy := @btnCloseClick; FilenameEdit1 := TfpgFileNameEdit.Create(self); with FilenameEdit1 do begin Name := 'FilenameEdit1'; SetPosition(28, 28, 360, 24); ExtraHint := ''; FileName := ''; Filter := ''; InitialDir := ''; TabOrder := 1; end; Label1 := TfpgLabel.Create(self); with Label1 do begin Name := 'Label1'; SetPosition(164, 12, 80, 15); FontDesc := '#Label1'; Hint := ''; Text := 'Audio file'; end; Button1 := TfpgButton.Create(self); with Button1 do begin Name := 'Button1'; SetPosition(400, 28, 412, 23); FontDesc := '#Label1'; Hint := ''; ImageName := ''; TabOrder := 3; Text := 'Draw Wave Form'; onclick := @btndrawClick; end; Custom1 := TfpgWidget.Create(self); with Custom1 do begin Name := 'Custom1'; SetPosition(2, 68, 836, 404); OnPaint := @drawwave; end; {@VFD_BODY_END: waveform} {%endregion} ordir := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))); // Height := 197; {$IFDEF Windows} {$if defined(cpu64)} fnsf := ordir + 'lib\Windows\64bit\LibSndFile-64.dll'; fnmp := ordir + 'lib\Windows\64bit\LibMpg123-64.dll'; {$else} fnsf := ordir + 'lib\Windows\32bit\LibSndFile-32.dll'; fnmp := ordir + 'lib\Windows\32bit\LibMpg123-32.dll'; {$endif} FilenameEdit1.FileName := ordir + 'sound\test.mp3'; {$ENDIF} {$IFDEF Darwin} {$IFDEF CPU32} opath := ordir; opath := copy(opath, 1, Pos('/uos', opath) - 1); FilenameEdit1.FileName := ordir + 'sound/test.mp3'; fnsf := opath + '/lib/Mac/32bit/LibSndFile-32.dylib'; fnmp := opath + '/lib/Mac/32bit/LibMpg123-32.dylib'; {$ENDIF} {$IFDEF CPU64} opath := ordir; opath := copy(opath, 1, Pos('/uos', opath) - 1); FilenameEdit1.FileName := ordir + 'sound/test.mp3'; fnsf := opath + '/lib/Mac/64bit/LibSndFile-64.dylib'; fnmp:= opath + '/lib/Mac/64bit/LibMpg123-64.dylib'; {$ENDIF} {$ENDIF} {$if defined(CPUAMD64) and defined(linux) } fnsf := ordir + 'lib/Linux/64bit/LibSndFile-64.so'; fnmp := ordir + 'lib/Linux/64bit/LibMpg123-64.so'; FilenameEdit1.FileName := ordir + 'sound/test.mp3'; {$ENDIF} {$if defined(cpu86) and defined(linux)} fnsf := ordir + 'lib/Linux/32bit/LibSndFile-32.so'; fnmp := ordir + 'lib/Linux/32bit/LibMpg123-32.so'; FilenameEdit1.FileName := ordir + 'sound/test.mp3'; {$ENDIF} {$if defined(linux) and defined(cpuarm)} fnsf := ordir + 'lib/Linux/arm_raspberrypi/libsndfile-arm.so'; fnmp := ordir + 'lib/Linux//arm_raspberrypi/libmpg123-arm.so'; FilenameEdit1.FileName := ordir + 'sound/test.mp3'; {$ENDIF} {$if defined(linux) and defined(cpuaarch64)} fnsf := ordir + 'lib/Linux/aarch64_raspberrypi/libportaudio_aarch64.so'; fnmp := ordir + 'lib/Linux/aarch64_raspberrypi/libmpg123_aarch64.so'; FilenameEdit1.FileName := ordir + 'sound/test.mp3'; {$ENDIF} {$IFDEF freebsd} {$if defined(cpu64)} fnsf := ordir + 'lib/FreeBSD/64bit/libsndfile-64.so'; fnmp := ordir + 'lib/FreeBSD/64bit/libmpg123-64.so'; {$else} fnsf := ordir + 'lib/FreeBSD/32bit/libsndfile-32.so'; fnmp := ordir + 'lib/FreeBSD/32bit/libmpg123-32.so'; {$endif} FilenameEdit1.FileName := ordir + 'sound/test.mp3'; {$ENDIF} {$if defined(CPUAMD64) and defined(linux) } // For Linux amd64, check libsndfile.so if uos_TestLoadLibrary(PChar(fnsf)) = false then fnsf := fnsf + '.2'; {$endif} if uos_LoadLib(nil, PChar(fnsf), PChar(fnmp), nil, nil, nil, nil) = 0 then button1.Enabled := True else begin button1.Enabled := False; button1.Text := 'Error while loading libraries :-('; end; end; procedure MainProc; var frm: Twaveform; begin fpgApplication.Initialize; try if fpgStyleManager.SetStyle('Chrome silver flat menu') then fpgStyle := fpgStyleManager.Style; fpgApplication.CreateForm(Twaveform, frm); fpgApplication.MainForm := frm; frm.Show; fpgApplication.Run; finally uos_free; frm.Free; end; end; begin MainProc; end.