|
Administrator
|
**@rfetn42: your post was wrongly deleted, sorry**
The short story is I want to replace an old free version of ZaraRadio Free Edition (radio station automation software) which has not been updated in years with a new Object Pascal program based on my own requirements. I am currently using a recently downloaded flat version of UOS in Lazarus 4.6 and FPC 3.2.2 on a beefy laptop running Fedora Linux 44 (Workstation Edition). Using the provided examples, I created an application that plays MP3s, shows the position on a track bar, jumps to random positions via the track bar, implements VU meters, and displays waveforms. One major requirement of mine that ZaraRadio Free Edition cannot do is find the last sample of an audio file before it drops below a certain threshold. In other words, as a song fades out, when it drops below a certain level, I want to start the next song playing. Without examples on how to do that, I ask several AIs how they would do it. They keep giving me code that will not compile calling functions that do not exist and when I call them on that, I eventually can get code that at least compiles after I fix a few things, but then ultimately will not work. For example: // uos_InputBufferRead returns data in bytes. 1 sample (16-bit) = 2 bytes. BytesRead := uos_InputBufferRead(ScanPlayer, InIdx, @Buffer[0], SizeOf(Buffer)); I did locate an example using “uos_InputSetLevelArrayEnable” and “uos_EndProc” and in the end procedure called “uos_InputGetLevelArray” to get what I think is averaged data, but I cannot get the sample number where the fadeout started. Is there a good example out there how to do what I suspect should be relatively simple task? From what I have learned, it may be complex as a MP3 file has to be reconstituted and the real solution will resemble something like the waveform example. |
|
Administrator
|
@rfetn42: Welcome to uos forum.
I apologize for your post wrongly deleted. It is possible to do what you asked, I will give you a demo asap. Write you later. Fred |
|
Administrator
|
This post was updated on .
Hello.
Not sure that i understood what you want but for this you may use uos_LoopProcIn(). Example: var Inputlength1 : integer; mixisdone : boolean = false; procedure tsongplayerfo.createplayer(); begin ... Inputlength1 = uos_Inputlength(theplayer, Inputindex1); uos_InputSetPositionEnable(theplayer, Inputindex1, 1); uos_OutputSetLevelEnable(theplayer, Outputindex1, 2); uos_LoopProcIn(theplayer, Inputindex1, @LoopProcPlayer1); ... end; procedure tsongplayerfo.LoopProcPlayer1(); var mixlevel : float = 0.2 ; // the minimum volume startcheckposition : integer = 10000 ; // the position when to start to check level begin if mixisdone = false then // was the mix already done if uos_InputPosition(theplayer, Inputindex1) > Inputlength1 - startcheckposition then // when start to check volume if (uos_outputGetLevelLeft(theplayer, outputindex1) < mixlevel) or (uos_outputGetLevelright(theplayer, outputindex1 < mixlevel) then // the level when to do the mix begin mixisdone = true; uos_play(theplayer2); //play the player2 to mix end; end; ------------------------------------------ If you want that more than one sample is used and do a average you can use a array to store uos_outputGetLevel() and in LoopProcPlayer1 fill that array at each loop on a new index, something like var levelar : array of float; indexar: integer = 0; lengthofar : integer = 100; // in init setlength(levelar, lengthofar) // set the length of the array procedure tsongplayerfo.LoopProcPlayer1(); var mixlevel : float = 0.2 ; // the minimum volume startcheckposition : integer = 10000 ; // the position when to start to check level begin if mixisdone = false then // was the mix already done if uos_InputPosition(theplayer, Inputindex1) > Inputlength1 - startcheckposition then // when start to check volume then begin levelar[indexar] :=( (uos_outputGetLevelLeft(theplayer, outputindex1) + (uos_outputGetLevelRight(theplayer, outputindex1) / 2); if indexar = lengthofar - 1 then begin // calculate the average of the array I let you do it if averageofarray <= mixlevel then begin mixisdone = true; uos_play(theplayer2); //play the player2 to mix end else indexar := 0; end else inc(indexar); end; |
|
Thank you for the reply. I was able to get the first of your examples working. At first it did not work, getting caught in the default frame being too large to catch the fade out of the song. Dropping the frame rate to 4,096 did the trick as well as increasing the "startcheckposition" to one million.
But the level at that resolution dropped below 0.2 too early and the next song started playing many seconds too early. Something I was sure would happen occasionally. What I really want to do is start at the end of the MP3 file and look for the first place the level increases above 0,2. Then note that sample number. This could happen while the song starts playing the main player and a second player does the reverse level check. Then when the main player hits that sample number, it would start the next player playing. Does that make sense? I did get really excited to have the second song start automatically playing even if it was too early. Proved what I want to do is possible. |
|
Administrator
|
This post was updated on .
Hello and sorry for the delay.
About calculate the level from the end of a second player, of course you can do it, take a look at formspectrum example. But imho it is more complicated because you need to load a second player and have to calculate the relative position. Did you try the second demo in first post using a array of levels, it should be more accurate than using only one buffer of samples like in first example. Of course you must adapt the parameters, in the demo they are only to give the idea. |
|
Good news. I pondered and tried the ideas from your latest post, but as I was getting it to work, I realized it was not exactly what I wanted to do.
Then I returned to the simple player code. First I added a line to put the right level, left level, and current sample into the form's caption. Then I added a button to move the current play position to the end. Then I checked the reverse box and let it start playing. Then I hit the end button and the song immediately stopped playing. After some guesses, I figured out I needed to go to the end of the song minus the frame rate minus one. Then when I hit the end button, I could see the left and right levels start at zero and work their way up as the song faded up backwards. Now I have logic than can calculate the sample where the volume falls below a certain threshold. Next I need to isolate that and see if I can accomplish the same thing in the same player. Hopefully I can share that logic towards the end of the week. |
| Free forum by Nabble | Edit this page |
