Hello!!
There a way to run a sound directly from a TMemoryStream without using the net or going to save a file. I only saw uos_AddFromFile (PlayerIndex1, (pchar (SoundFilename))); but a function of the type ms: TMemoryStream uos_AddFromMStream (PlayerIndex1, ms); or by passing the file extension if needed uos_AddFromMStream (PlayerIndex1, ms, ext); it's possible? I have an encrypted data structure where I fetch the files and decode them. Everything happens in memory. So to me it is fundamental the use of TMemoryStream without writing anything. uos_AddFromFile () I can not use it. I saw that in "uos_libsndfile.pas" in addition to "sf_open ()" there is also "sf_open_virtual" I do not understand how to exploit it . Thanks, any help is appreciated |
Administrator
|
Hello and welcome.
You may use: uos_CreatePlayer(0); // create the player uos_AddIntoDevOut(0); // add a output to sound card uos_AddFromFile(0,pchar(thesound)); // add a input from file ... uos_PlayNoFree(0); // you may play how many times without re-load it ... uos_FreePlayer(0); // when you do not need it anymore. I am busy to add a new method: uos_AddFromFileIntoMemory(). It will copy the data of the file into memory. Then you may play it directly from memory. I will release it ASAP (I am over-booked now). PS: But maybe you want something else. Fre;D |
Hello, thank you for your work !!!
I found this library a few days ago, and I'm thinking to use only this. In this case, the real problem is that I do not have a PATH which can give uos_AddFromFile (0, pchar (???)). The data structure in question is a single file that contains different encrypted data such as sounds and more. A very bad solution would be to save the TMemoryStream decrypted file so as to have the path to load. But this is what I want to avoid. As well as in my case, this feature might be useful to those using a game engine combine with a data structure containing the sounds and other. I saw the "AddFromFileIntoMemory ()" method just added but the problem is always the same that I have NO PATH. The audio files are ready to use it only in TMemoryStream memory. Anyway thanks for your time !! |
Administrator
|
AddFromFileIntoMemory () does 2 things: - Decode the file and store the data into a array. - Create a input that will use that array. If the array already exists, thanks, 1 job less to do ;-) You may use FiletoBuffer() if you need to create the buffer. Up to you to do what you want with that array. function FiletoBuffer(Filename): TDArFloat; // for creating the buffer Fre;D |
Hello,
certainly start with available files but I can not give a multi-encrypted file structure as PATH!! FiletoBuffer -> theplayer.AddFromFile -> "sf_open(FileName???, SFM_READ, sfInfo)" sf_open (const char *path, int mode, SF_INFO *sfinfo) ; The problem is that this implementation will always depend on a PATH file But if used: sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; From site lib: "Opens a soundfile from a virtual file I/O context which is provided by the caller. This is usually used to interface libsndfile to a stream or buffer based system. Apart from the sfvirtual and the user_data parameters this function behaves like sf_open." In addition to the implementation through "PATH" and can implement a solution without asking for any file path using "sf_open_virtual"? Thanks for your time!! |
Administrator
|
Hello.
Added in last commit d35cb28 AddFromMemory(...) to play from memory stream. Fre;D |
Thanks for the method!
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. |
Hello,
I try to help by implementing a method for using sf_open_virtual that solves the problem. This is my implementation: Type PMemoryStream = ^TMemoryStream; sf_count_t = Int64; //pm_get_filelen = ^tm_get_filelen; tm_get_filelen = function (pms: PMemoryStream): sf_count_t; //pm_seek = ^tm_seek; tm_seek = function (offset: sf_count_t; whence: Integer; pms: PMemoryStream): sf_count_t; //pm_read = ^tm_read; tm_read = function (buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t; //pm_write = ^tm_write; tm_write = function (const buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t; //pm_tell = ^tm_tell; tm_tell = function (pms: PMemoryStream): sf_count_t; TSF_VIRTUAL = packed record sf_vio_get_filelen : tm_get_filelen; sf_vio_seek : tm_seek; sf_vio_read : tm_read; sf_vio_write : tm_write; sf_vio_tell : tm_tell; end; function m_get_filelen(pms: PMemoryStream): sf_count_t; begin Result:= pms^.Size; end; function m_seek(offset: sf_count_t; whence: Integer; pms: PMemoryStream): sf_count_t; Const SEEK_SET = 0; SEEK_CUR = 1; SEEK_END = 2; begin case whence of SEEK_SET: Result:= pms^.Seek(offset, soFromBeginning); SEEK_CUR: Result:= pms^.Seek(offset, soFromCurrent); SEEK_END: Result:= pms^.Seek(offset, soFromEnd); end; end; function m_read(buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t; begin Result:= pms^.Read(buf^,count); end; function m_write(const buf: Pointer; count: sf_count_t; pms: PMemoryStream): sf_count_t; begin Result:= pms^.Write(buf^,count); end; function m_tell(pms: PMemoryStream): sf_count_t; begin Result:= pms^.Position; end; procedure TSSoundUOS.TestLibSndFile; Var sfInfo: TSF_INFO; sfVirtual: TSF_VIRTUAL; procedure ShowInfo; Var sl: TStringList; begin sl:= TStringList.Create; try with sfInfo do begin sl.Add('frames: '+IntToStr(frames)); sl.Add('samplerate: '+IntToStr(samplerate)); sl.Add('channels: '+IntToStr(channels)); sl.Add('format: '+IntToStr(format)); sl.Add('sections: '+IntToStr(sections)); sl.Add('seekable: '+IntToStr(seekable)); end; ShowMessage(sl.Text); finally sl.Free; end; end; Const path_test = 'c:\test.flac'; //for simulate Var ms: TMemoryStream; begin FillChar(sfInfo, SizeOf(sfinfo), 0); sf_open(path_test, SFM_READ, sfInfo); ShowInfo; with sfVirtual do begin sf_vio_get_filelen := m_get_filelen; sf_vio_seek := m_seek; sf_vio_read := m_read; sf_vio_write := m_write; sf_vio_tell := m_tell; end; FillChar(sfInfo, SizeOf(sfinfo), 0); ms:= TMemoryStream.Create; try ms.LoadFromFile(path_test); ms.Position:= 0; sf_open_virtual(@sfVirtual, SFM_READ, @sfInfo, @ms); ShowInfo; finally ms.Free; end; end; 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 Streamin [x] .Data.HandleSt: = sf_open (FileName, SFM_READ, sfinfo); Streamin [x] .Data.HandleSt: = sf_open_virtual(@sfVirtual, SFM_READ, @sfInfo, @ms); is it solve for libsndfile |
Administrator
|
Hello.
Added in last commit 0746826 ConsolePlayMemory.pas to show how to use memory buffer as input. Fre;D |
Thanks for add
|
Administrator
|
> Thanks for add
Huh, is it useful for you ? Did you add the buffer into ressource? I am busy to add addFromMemoryStream(), I hope to commit it asap. Fre;D |
It is useful for UOS, so for all.
For my problem, when you have time. Thank you |
Administrator
|
> For my problem, when you have time.
Did you try to convert the buffer into file, then add this to ressource, then load the file from ressource and convert it into buffer ? In short, if you can convert the buffer into file (with a TFileStream) and TMemoryStream into a buffer, you get it ;-) It is not very complicated, there are code for convert data of TMemoryStream into buffer in uos if you need it now. But, I am very sorry, now I can do it, too much work. ;-( Fre;D |
It is possible by storing in the structure, the preloaded data using libsndfile (buffer and parameters). But NOT in the original format.
In practice by altering the encrypted data structure it is possible. My goal is to use only UOS, but keeping the data structure as independent as possible. In the future, if they will be available direct support for the TMemoryStream will be a nice addition. |
Administrator
|
Hello.
Added procedure uos_File2File() in last commit 0746826..e96cd3d. You may use this to save all type of audio file into a pcm file (= save the buffer into file). For example, to save a file in format pcm: uos_File2File(pchar(SoundFilenameIN),pchar(SoundFilenameOUT), 1, 1); This file could be used for ressource. Then convert it back to buffer. PS: Only integer 32/16 is allowed for uos_File2File() (not float 32, but it will be converted by uos if needed). Fre;D |
Administrator
|
In reply to this post by Phoenix
Hello Phoenix ?
Did you try with TRessourceStream ? http://lazarus-ccr.sourceforge.net/docs/rtl/classes/tresourcestream.html I think that you have everything to do what you want: 1) uos_File2File(pchar(SoundFilenameIN),pchar(SoundFilenameOUT), 1, 1); (This for create the ressource) 2) TRessourceStream to load the ressource. 3) Convert the data of TRessourceStream into a buffer of float. 4) Use it with uos_AddFromMemoryBuffer() Fre;D |
Administrator
|
> 3) Convert the data of TRessourceStream into a buffer of float.
Hello. Here how to convert TRessourceStream into buffer: uses ..., ctypes,...; var len : integer; buffer : array of cfloat; ARessorceStream : TRessorceStream; ... try ... // the ARessorceStream was created len := ARessorceStream.Size; SetLength(buffer, 0); SetLength(buffer, len div SizeOf(buffer[0])); ARessorceStream.ReadBuffer(buffer[0], Length(buffer) * SizeOf(buffer[0])); finally ARessorceStream.Free; end; Fre;D |
Hello,
sorry for the wait, I tested everything and works perfectly. No need to use TResourceStream because it also works with TMemoryStream. It basically a bypass of linsndfile library (for the accuracy of all libraries for sound format). Using the decoded buffer and then just load only PortAudio. This is an interesting feature. But in my case, you lose the advantage of starting from files in original format as flac, mp3 .. Decrypt a large file such as .wav format is inconvenient. It is true that sf_open_virtual can only solve for libsndfile but it would still be an additional feature (apart from a possible problem at the end of the sound seems that the solution was nearly reached "Tuos_Player.AddFromMStream"). Maybe I'm wrong to focus on sf_open_virtual but by a non-expert point of view, it may seem promising. Thanks for your help |
Administrator
|
> Maybe I'm wrong to focus on sf_open_virtual
Hello. No and excuse me if I did not speak over this. Of course it is a great addition and I will take a look asap. But before to commit it, I want to do the same for mpg123 and opus. It will not be very hard because it was already done for web-streaming. I have just to adapt the code for a independent TMemoryStream of compressed audio. Many thanks to contribute to uos. Fre;D |
Administrator
|
In reply to this post by Phoenix
> is it solve for libsndfile
Huh, is it working for you ? I have try your code but it crash after +- 1 second playing. What result do you have ? Fre;D |
Free forum by Nabble | Edit this page |