Recent

Author Topic: [SOLVED] UOS: play from TMemoryStream  (Read 14635 times)

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: UOS: play from TMemoryStream
« Reply #15 on: March 02, 2017, 02:35:06 pm »
Quote
he virtual file is not a general concept

And it is also a concept that I will not use.

It seems to me something for hackers (you know those people who prefer to use their brain to steal vs to create).

uos_AddFromMemory(...) uses a array of float as memory stream.

Up to the user to create that input from what he want.

Fre;D
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

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: UOS: play from TMemoryStream
« Reply #16 on: March 02, 2017, 03:12:52 pm »
Quote
he virtual file is not a general concept

And it is also a concept that I will not use.

It seems to me something for hackers (you know those people who prefer to use their brain to steal vs to create).

uos_AddFromMemory(...) uses a array of float as memory stream.

Up to the user to create that input from what he want.

Fre;D
I am a bit flabbergasted by that response.

I'm sure it is all due to the language barrier but, for sure there isn't anything hackish about a library (such as libsndfile) offering functionality to implement a virtual backend that can be used to load and save data.

Libraries like libsndfile provide such feature in order to let their functionality integrated independent of the programming language being used.

That allows for better integration in the programming language, in case things can not be done using the 'normal' offered functions to accomplish the task.

In that regards it is nothing more then adding events to a form. If you don't implement the event then you do not use that functionality if you do use the event then you've added support for it. f.e. handling mouse-clicks.

FPC makes heavy use of streams, simply because it allows a simple more or less uniform way whether a user wishes to load something from a file, memory, the internet or whatever the stream retrieve it data from.

Components/classes like zipstream, structured storage and resource streams are a good example of allowing the user to store their data in whatever stream format and offer a uniform way to extract data from those streams.

Quote
uos_AddFromMemory(...) uses a array of float as memory stream.
While that is a good start, it still does not allow for the user to use what he/she likes the most about FPC: working with streams.

Besides that, in case the data is to be 'decoded' first, then the end-user is not allowed to just point to the memory location of the 'encoded' stream.

Therefor a function like uos_addFromMemory() will still not allow the end-user to use streams.

User would have to extract the data from the stream first, store it into memory and then offer it to this function (just as inefficient as the previous writeln exampe i showed).

btw: Yes, that might be an array of float (that is, in case the sound format expects to consist out of floats, otherwise it's another type).

The PM i sended Fred vS is a simple implementation of the virtual functions offered by libsndfile and uses FPC streams to load from and save to. libsndfile itself does not care where the data is actually coming from.

To Fred vS i would like to say:

UOS is your library and you are the maintainer. Either you would like to support FPC streams or not. No hard feelings either way.

The only thing i did is responding to TS question in which TS expressed his question if it was possible to load data from a Stream.

The virtual functions of libsndfile allows to do so. The only thing i do not know if UOS itself is able to make use of that (in theory it should be able to).
« Last Edit: March 02, 2017, 03:15:26 pm by molly »

Phoenix

  • Jr. Member
  • **
  • Posts: 87
Re: UOS: play from TMemoryStream
« Reply #17 on: March 02, 2017, 04:56:27 pm »
Hello @Fred vS,

function uos_AddFromMemory (PlayerIndex: cint32; MemoryBuffer: PDArFloat; OutputIndex: cint32;
   SampleFormat: cint32; SampleRate: cint32; Channels: cint32; FramesCount: cint32): cint32;

It did not accept as a parameter an TMemoryStream but will be useful.
I try to help by implementing a method for using sf_open_virtual that solves the problem.
This is my implementation:  :D

Code: Pascal  [Select][+][-]
  1. Type
  2.  PMemoryStream = ^TMemoryStream;
  3.  sf_count_t = Int64;
  4.  
  5.  //pm_get_filelen = ^tm_get_filelen;
  6.  tm_get_filelen =
  7.   function (pms: PMemoryStream): sf_count_t;
  8.  //pm_seek = ^tm_seek;
  9.  tm_seek =
  10.   function (offset: sf_count_t; whence: Integer; pms: PMemoryStream): sf_count_t;
  11.  //pm_read = ^tm_read;
  12.  tm_read =
  13.   function (buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t;
  14.  //pm_write = ^tm_write;
  15.  tm_write =
  16.   function (const buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t;
  17.  //pm_tell = ^tm_tell;
  18.  tm_tell =
  19.   function (pms: PMemoryStream): sf_count_t;
  20.  
  21.  TSF_VIRTUAL = packed record
  22.   sf_vio_get_filelen  : tm_get_filelen;
  23.   sf_vio_seek         : tm_seek;
  24.   sf_vio_read         : tm_read;
  25.   sf_vio_write        : tm_write;
  26.   sf_vio_tell         : tm_tell;
  27.  end;
  28.  
  29. function m_get_filelen(pms: PMemoryStream): sf_count_t;
  30. begin
  31.  Result:= pms^.Size;
  32. end;
  33.  
  34. function m_seek(offset: sf_count_t; whence: Integer; pms: PMemoryStream): sf_count_t;
  35. Const
  36.  SEEK_SET = 0;
  37.  SEEK_CUR = 1;
  38.  SEEK_END = 2;
  39. begin
  40.  case whence of
  41.   SEEK_SET: Result:= pms^.Seek(offset, soFromBeginning);
  42.   SEEK_CUR: Result:= pms^.Seek(offset, soFromCurrent);
  43.   SEEK_END: Result:= pms^.Seek(offset, soFromEnd);
  44.  end;
  45. end;
  46.  
  47. function m_read(buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t;
  48. begin
  49.  Result:= pms^.Read(buf^,count);
  50. end;
  51.  
  52. function m_write(const buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t;
  53. begin
  54.  Result:= pms^.Write(buf^,count);
  55. end;
  56.  
  57. function m_tell(pms: PMemoryStream): sf_count_t;
  58. begin
  59.  Result:= pms^.Position;
  60. end;
  61.  
  62. procedure TSSoundUOS.TestLibSndFile;
  63. Var
  64.  sfInfo: TSF_INFO;
  65.  sfVirtual: TSF_VIRTUAL;
  66.  
  67.  procedure ShowInfo;
  68.  Var
  69.   sl: TStringList;
  70.  begin
  71.   sl:= TStringList.Create;
  72.   try
  73.    with sfInfo do
  74.    begin
  75.     sl.Add('frames: '+IntToStr(frames));
  76.     sl.Add('samplerate: '+IntToStr(samplerate));
  77.     sl.Add('channels: '+IntToStr(channels));
  78.     sl.Add('format: '+IntToStr(format));
  79.     sl.Add('sections: '+IntToStr(sections));
  80.     sl.Add('seekable: '+IntToStr(seekable));
  81.    end;
  82.    ShowMessage(sl.Text);
  83.   finally
  84.    sl.Free;
  85.   end;
  86.  end;
  87.  
  88. Const
  89.  path_test = 'c:\test.flac'; //for simulate
  90. Var
  91.  ms: TMemoryStream;
  92. begin
  93.  FillChar(sfInfo, SizeOf(sfinfo), 0);
  94.  sf_open(path_test, SFM_READ, sfInfo);
  95.  ShowInfo;
  96.  
  97.  with sfVirtual do
  98.  begin
  99.   sf_vio_get_filelen  := m_get_filelen;
  100.   sf_vio_seek         := m_seek;
  101.   sf_vio_read         := m_read;
  102.   sf_vio_write        := m_write;
  103.   sf_vio_tell         := m_tell;
  104.  end;
  105.  
  106.  FillChar(sfInfo, SizeOf(sfinfo), 0);
  107.  ms:= TMemoryStream.Create;
  108.  try
  109.   ms.LoadFromFile(path_test);
  110.   ms.Position:= 0;
  111.   sf_open_virtual(@sfVirtual, SFM_READ, @sfInfo, @ms);
  112.   ShowInfo;
  113.  finally
  114.   ms.Free;
  115.  end;
  116. end;  
  117.  

This work on Windows 10 64bit and Lazarus 1.6.2 FPC 3.0.0 64bit  ;D

Now create this

function Tuos_Player.AddFromMStream(ms: TMemoryStream; OutputIndex: cint32;
  SampleFormat: cint32 ; FramesCount: cint32 ): cint32;

Replace the code that uses sf_open with sf_open_virtual

Code: Pascal  [Select][+][-]
  1. Streamin [x] .Data.HandleSt: = sf_open (FileName, SFM_READ, sfinfo);
  2.  
  3. Streamin [x] .Data.HandleSt: = sf_open_virtual(@sfVirtual, SFM_READ, @sfInfo, @ms);
  4.  

is it solve for libsndfile, you only have to test all  :)


molly

  • Hero Member
  • *****
  • Posts: 2330
Re: UOS: play from TMemoryStream
« Reply #18 on: March 02, 2017, 05:03:19 pm »
This is my implementation:  :D
Shame as that is (almost) exactly what i sended Fred Vs in my PM to him as well ;-)

Quote
Now create this

function Tuos_Player.AddFromMStream(ms: TMemoryStream; OutputIndex: cint32;
  SampleFormat: cint32 ; FramesCount: cint32 ): cint32;

Replace the code that uses sf_open with sf_open_virtual

Code: Pascal  [Select][+][-]
  1. Streamin [x] .Data.HandleSt: = sf_open (FileName, SFM_READ, sfinfo);
  2.  
  3. Streamin [x] .Data.HandleSt: = sf_open_virtual(@sfVirtual, SFM_READ, @sfInfo, @ms);
  4.  

is it solve for libsndfile, you only have to test all  :)
Would that indeed be enough for UOS to be able to add streaming support in a safe manner ?

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: UOS: play from TMemoryStream
« Reply #19 on: March 02, 2017, 07:06:10 pm »
If you want to use a memorystream, it is up to you.
But, AFAIK, a memorystream needs data.

Then, only use AddFromMemory(data_of_memorystream).

Why do you want to work with streams?
uos does the seek(), read() in the main loop.

In uos there is a utility: 
Code: Pascal  [Select][+][-]
  1. bufferdata := FiletoMemory(filename);

Then store that bufferdata into ressource.

After this, you may use:
uos_AddFromMemory (bufferdata,...);

function uos_AddFromMemory (PlayerIndex: cint32; MemoryBuffer: PDArFloat; OutputIndex: cint32;
   SampleFormat: cint32; SampleRate: cint32; Channels: cint32; FramesCount: cint32): cint32;

It did not accept as a parameter an TMemoryStream but will be useful.

OK, I will add a demo in uos to show how to do  ;D

Fre;D
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

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: UOS: play from TMemoryStream
« Reply #20 on: March 02, 2017, 07:19:23 pm »
If you want to use a memorystream, it is up to you.
Meaning that you won't consider adding support for streams ?

A decision i personally can't understand at all nor have i seen any valid reason(s) to not support streams but, it is fine with me if that is to be the choice.

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: UOS: play from TMemoryStream
« Reply #21 on: March 02, 2017, 07:32:59 pm »
If you want to use a memorystream, it is up to you.
Meaning that you won't consider adding support for streams ?

What are you taking?
uos is full off streams.
OK, I will add a function with TMemoryStream as input.

Thanks for all.

Fre;D
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

Phoenix

  • Jr. Member
  • **
  • Posts: 87
Re: UOS: play from TMemoryStream
« Reply #22 on: March 03, 2017, 10:40:22 am »
Hello,

@molly
After all, we used the same sample in c as a starting point.  ;)

I have tested the changes and indeed the sound works perfectly, but at the end of the sound crashes. Perhaps I created a bug or change is not enough. Even using PlayNoFree and without the Free TMemoryStream not solve.

Aspect of the implementation of Free vS but I was curious to try.  :)

@Fred vS
Thanks to the decision to add the method!!  :D

Thank you all!!

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: UOS: play from TMemoryStream
« Reply #23 on: March 03, 2017, 01:26:20 pm »
Quote
OK, I will add a demo in uos to show how to do  ;D

Hello.

Added ConsolePlayMemory.pas in last commit  d35cb28..0746826 to show how to use memory buffer as input.
Note that with this added in ressource you will not need to load audio libraries anymore.

uos will do everything alone (only portaudio is needed).

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

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

Phoenix

  • Jr. Member
  • **
  • Posts: 87
Re: UOS: play from TMemoryStream
« Reply #24 on: March 06, 2017, 10:31:16 am »
Thanks for add  :)

Phoenix

  • Jr. Member
  • **
  • Posts: 87
Re: UOS: play from TMemoryStream
« Reply #25 on: March 12, 2017, 10:59:23 am »
The solution has been found !!!  :D :D :D
For those interested look
http://uos.2369694.n4.nabble.com/Load-sound-from-TMemoryStream-td28.html

 

TinyPortal © 2005-2018