Load sound from TMemoryStream

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
78 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
Hello,
I sent you an email with all the source for testing. I've changed a little but the result is the same: run the audio files without crashing. On Win 10 64bit and Laz last version with FPC 3.0.2 64bit.
But there is definitely an abnormal behavior that I can not identify.
You probably need to change something.

 Thanks
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Hello.

In last commit: 4f61f07..dc47eb  was added:

Method: AddFromMemoryStream(...) and
Demo: ConsolePlayMemoryStream.lpi

Could you try it?

Warning: Only LibSndFile is implemented, so it will work only for wav, ogg, flac audio format.
Mp3, opus and custom audio format will come asap.

PS: You are added in the list of the great contributors.
Many thanks for your great contribution.

> I sent you an email with all the source for testing.
Ho, thanks, I will take a look. (but last commit should work, I hope).

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
Yes, it works!!!

Thanks so much!!!
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
I found a small memory leak:
in Tuos_Player.AddFromMemoryStream ()
..
Streamin [x] .Data.MemoryStream: = TMemoryStream.Create; //memory leak
Streamin [x] .Data.MemoryStream: = MemoryStream;
..

THANKS AGAIN
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
This post was updated on .
> Streamin [x] .Data.MemoryStream: = TMemoryStream.Create; //memory leak

Ha, ok, I will fix it.
[EDIT] Fixed in last commit b74653e..5c534bf.

Huh, you should use last commit b74653e..5c534bf because there was a big bug in previous release.

uos was not able to load mp3, opus or aac files anymore. ;-(

Fixed now, please, download last release.

Also mp3 is implemented for memory stream.
(With a bemol, all works but mpg123 set the length of a sound from a TMemoryStream to -1 and not seekable, I have to ask why in mpg123 forum)

Fre;D

Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fauri
When I build the consoleplaymemorystream project, I got a SIGSEGV error on line 4212 of uos.pas.

I realized too that "{$if defined(cpu64)}" doesn't work to me. Just the 32 bits libraries are loaded, and, if I force only 64 bits versions, uos_LoadLib returns -1.

By the way, I'm using Windows 10 x64, but with Lazarus 32 bits.
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
This post was updated on .
Hello tranks,

@Fauri
Yes, my error

add "cdecl;":

for example
- tm_get_filelen =
   function (pms: PMemoryStream): Tsf_count_t;
- function m_get_filelen(pms: PMemoryStream): sf_count_t;
 
VERSION OK
- tm_get_filelen =
   function (pms: PMemoryStream): Tsf_count_t; cdecl;
- function m_get_filelen(pms: PMemoryStream): sf_count_t; cdecl;

FOR ALL
 tm_get_filelen/m_get_filelen
 tm_seek/m_seek
 tm_read/m_read
 tm_write/m_write
 tm_tell/m_tell

@Fred vS
In addition to mp3 support there is a small change:
...
{$IF DEFINED(webstream)} //< remove compiler directive
function mpg_read_stream(ahandle: Pointer; AData: Pointer; ACount: Integer): Integer; cdecl;
var  
...

Apart from the "length" problem, the mp3 format works well !!!

PS. Tsf_count_t/sf_count_t: one of the two is superfluous

  Thanks
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Hello.

> add "cdecl;"
Huh, of course, thanks to note it, fixed in last commit e6d2d50..b759b5a.

> {$IF DEFINED(webstream)} //< remove compiler directive
Re-huh, fixed  in last commit e6d2d50..b759b5a.

@ Phoenix --> thanks for your light.

> Apart from the "length" problem, the mp3 format works well !!!
Maybe with a new release of mpg123 it is fixed, I did not try yet.
But I suspect that mpg123 decides that the stream is not-seekable when using mpg123_open_handle().
(Or I did not catch something).

MemoryStream of Opus file is in progress (but not yet working perfectly).

Fre;D

Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
This post was updated on .
Hello,

I tried to solve the problem mp3:

During the research I found this but not working

mpg123_framelength
Return, if possible, the full (expected) length of track in the current frames.

mpg123_set_filesize
Override the value for the file size in bytes. Useful for getting sensible track length values in feed mode or for HTTP streams.

then I changed

Streamin [x] .Data.Length: = mpg123_length (Streamin [x] .Data.HandleSt);

with

Streamin [x] .Data.Length: = MemoryStream.Size;

sound works, but the length is in fact different from the version that file loads
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
In reply to this post by Phoenix
> Streamin [x] .Data.Length: = MemoryStream.Size;
> sound works, but the length is in fact different from the version that file loads

Yes, it is normal because MemoryStream.Size is the size of the compressed samples (mp3 format).
Not the size of the pcm (decoded frames).

For wav files, it works (you only have to (MemoryStream.Size - size of header) div sizeof(float32 or integer16/32)).  

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Hello.

Added AddFromMemoryStream() of Opus files.

WARNING: AddFromMemoryStream() has other parameters now.

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
Hello,
thanks to the latest addition !!!
Sorry for the stupid idea "MemoryStream.size" ... too tired
This morning I analyzed the source of the mpg123 library

This is my implementation for mpg_seek_stream ()

function mpg_seek_stream(ahandle: Pointer; offset: Integer;
 whence: Integer): Integer; cdecl;
var
 Stream: TStream absolute ahandle;
begin
 try
  case whence of
   SEEK_SET  : Result:= Stream.Seek(offset, soFromBeginning);
   SEEK_CUR  : Result:= Stream.Seek(offset, soFromCurrent);
   SEEK_END  : Result:= Stream.Seek(offset, soFromEnd);
   else
    Result:= 0;
  end;
 except
  Result := 0;
 end;
end;

Try it, should solve

PS. The "web" capabilities should benefit
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
> Try it, should solve

Wow, I will try it asap, many thanks.

By the way, it seems that it is possible to get the length a other way:

http://web.archive.org/web/20080801005127/http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=79

But, f course, your solution is much easier.

Fre;D



Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
This post was updated on .
In reply to this post by Phoenix
> function mpg_seek_stream()

Tested and committed c06bc7c..c5642af, many thanks Phoenix.

And https://sourceforge.net/p/mpg123/bugs/247/ ---> Closed (with lot of excuses )

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
This post was updated on .
Hello,
I wanted to try running a .opus sound.
I compiled the example SimplePlayer:
there is an error in the library name "LibOpusFile-64.so" instead of "LibOpusFile-32.dll".
But even with the correct name is not loading.
It seems to fail "of_Handle: = DynLibs.SafeLoadLibrary (libfilename)"
In fact, removing only that everything is ok.

Win10 64bit
Lazarus fpc 1.6.4 3.0.2 32bit

PS.
I downloaded from the site of the library zip "opusfile-0.7-win32" and the files are identical so if exe 32bit and 32bit dll should work
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
This post was updated on .
> I wanted to try running a .opus sound.

LibOpusFile-32.dll.dll has libopus-0.dll for dependency.

You should copy /uos/examples/lib/Windows/32bit/libopus-0.dll into your windows/system directory.

That is the problem with dynamic loading of libraries, if there are dependencies...

The trick would be to add a library search patch before LoadLibrary().

It is in the todo list.

Fre;D

PS: Opus file is the future, same format for web streaming of music or voip, better quality than mp3 (with < size), decoder-incoder in the same library and open-source.

One of the creator of opus is also the creator of library SoundFile.

But opus is very young (same age than uos : 2012).

> there is an error in the library name "LibOpusFile-64.so" instead of "LibOpusFile-32.dll".
Oops, well seen, fixed (huh, I do not use Windows any more).
Also, by default for SimplePlayer demo, LibOpusFile-32.dll is not loaded.

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
Thank you,
for the quick response !!

PS. Yes, library opus is very attractive
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
Hello,

I looked at mpg_seek_url () method:

// should use this for pipes vs memorystream ?
function mpg_seek_url(ahandle: Pointer; aoffset: Integer): Integer;
var
  Stream: TStream absolute ahandle;
begin
  // pipe streams are not seekable but memory and filestreams are
  Result := 0;
  try
    if aoffset > 0 then
      Result := Stream.Seek(soFromCurrent, aoffset);
  except
    Result := 0;
  end;
end;

Missing "cdecl" and the parameters to seek () they are reversed (but it worked because "aoffset> 0" appears to be always false), "whence: Integer" missing.

I implemented this alternative I tested on Win10 64bit and Laz 32bit and it works:

function mpg_seek_url(ahandle: Pointer; offset: Integer;
 whence: Integer): Integer; cdecl;
var
 Stream: TInputPipeStream(*TStream*) absolute ahandle;
begin
 //(SEEK_END not supported for pipe stream)
 if whence = SEEK_END then
  Result:= -1 //(It seems to avoid the initial audio imperfections)
 else
  try
   //(SEEK_SET soFromBeginning not work but supported in laz docs)

   //(Note: also it works with a simple "Result:= 0")
   Result:= Stream.Seek(offset, soFromCurrent);
  except
   Result:= 0;
  end;
end;    

(*  
Consequently also it works well.
I do not know what difference there is in performance.
But I do not know if there is any function (combined with "web") requiring seek () to force

function mpg_seek_url(ahandle: Pointer; offset: Integer;
 whence: Integer): Integer; cdecl;
begin
 if whence = SEEK_END then
  Result:= -1
 else
  Result:= 0;
end;
*)  
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
> Missing "cdecl" and the parameters to seek () they are reversed

Hello Phoenix.

Oops, well seen, committed in e4eebf6..b4d2370. Many thanks.

I have try your new code but here, on Linux 64 and FreeBSD 64, I get a error message:

[parse.c:1037] error: Cannot seek back!

So I keep (for now) the old code.

Fre;D
1234