VOGONS


How do I feed mt32emu with data?

Topic actions

Reply 20 of 27, by sergm

User metadata
Rank Oldbie
Rank
Oldbie

Well... That reminds me how it commonly works 😀

Good news for you: when the buffer is so small, you may safely omit checking the internal synth's queue for being empty. Synth::isActive() will be true for long enough yet.

But I really really don't think that adding an extra function for just a single library client is worth. The library should not return some of the properties of its input that are directly available to the client. That's rather confusing. I think the isQueueEmpty() function should actually be private in contrast to isQueueFull(). Nobody should care of the former but most should care of the latter. I want to keep that info secret as an implementation detail 😀

Reply 21 of 27, by realnc

User metadata
Rank Oldbie
Rank
Oldbie

Whether the synth has finished its work or not is not an implementation detail. It's vital information that right now has to be inferred by other, indirect means (sample counting.) Maybe the name makes it sound like an implementation detail. Maybe think of hasMoreToRender() or hasFinished() or atEos() instead.

Synth::isActive() on its own is useless regardless of buffer size, since when there's total silence, it returns false, and thus this would lead into ending playback at some random point.

Furthermore, it's not restricted to "one client". All clients of the library have to implement the same code over and over again to determine whether there's anything more to render. smf2wav does it, as does the Qt GUI. Pretty much same code implemented multiple times. That's is code duplication, it just happens to be across different clients.

Note that the actual convention in other libraries is for the renderer to return the amount of samples written. When that amount is less than the requested amount, it means "I'm done." But since that modification to the code would be a bit more complicated, I offered a trivial alternative.

Reply 22 of 27, by sergm

User metadata
Rank Oldbie
Rank
Oldbie

At last, we came to the right reasoning 😀

Indeed, the current implementation of Synth::isActive() ignores the fact that something may remain in the queue. It should be updated as incomplete, but the user should not bother checking the output of two incomplete methods each of which returns nonsense individually.

Thank you for founding the bug and for your patience 😀 If you don't mind, please update the pull request in accordance.

As for the code duplication, that isn't completely correct. KingGuppy wrote smf2wav using the old library API, MidiParser instead uses the newer version. In fact, the function of smf2wav is nearly duplicated and as such it should be considered obsolete rather, I don't plan to add new features to that thing.

Reply 23 of 27, by realnc

User metadata
Rank Oldbie
Rank
Oldbie

Wait, the current behavior of isActive() is a bug? OK, I thought it's by design 😜 Although it did look a bit strange.

So its current semantics should be changed from "next rendered sample is not going to be silence" to "I have more stuff to render"?

Reply 24 of 27, by sergm

User metadata
Rank Oldbie
Rank
Oldbie

It was correct by design until I added the MIDI queue 😀 There were nothing more to do for the synth if all the parts are inactive and the reverb buffer is silent. But now, if there is something pending in the queue, the synth cannot claim it has nothing to do. Btw, when it renders in realtime, it always has something to do because we have implemented the silence shortcuts (again, for convenience). But it may actually be desired to detect the silence even in realtime and shutdown the audio output for awhile...

Reply 25 of 27, by sergm

User metadata
Rank Oldbie
Rank
Oldbie

Hmm, the current semantic is rather unclear:

// Returns true if hasActivePartials() returns true, or reverb is (somewhat unreliably) detected as being active.
MT32EMU_EXPORT bool isActive() const;

But the purpose is to detect whether the synth is finished, yes. As I mentioned, it may always return true even if the output is silence... I don't like this either in fact. It should better actually check the output for the silence as in AudioFileWriter. Or maybe implement a logarithmic volume decrease instead... The only argument is that an active part may be really silent for some time but then produce some sound before dying. This is why KingGuppy added the check for part activity, I guess.

Reply 26 of 27, by realnc

User metadata
Rank Oldbie
Rank
Oldbie

I added a check for a non-empty queue in isActive() and did a pull request.

When all events have been sent to the synth, clients will send note-off and sustain pedal release events. In that case, isn't the synth guaranteed to arrive at silence when all reverb has finished?

Reply 27 of 27, by sergm

User metadata
Rank Oldbie
Rank
Oldbie

Thanks for the PR, I'll review it ASAP.

Releasing a partial certainly takes some time before it dies away. Moreover, some patches decay especially slow. You can check this with soundtrack as an example. Therefore, you'll get a long tail that is barely audible (or not at all). That's why I sometimes think of logarithmic volume decrease at the end instead of waiting.