Author Topic: DigiBooster 2/3 plugin  (Read 29098 times)

krashan

  • Posts: 12
DigiBooster 2/3 plugin
« on: 31 Oct '14 - 10:53 »
I've finished the first working version of input plugin for *.dbm modules (DigiBooster 3, DigiBooster Pro 2).

xmp-digi3-0.4.zip [current version]

Features and limitations:

  • Based on libdigibooster3, which is the official DigiBooster 3 replayer.
  • Uses internal XMPlay file handling, so can play from URL-s as well.
  • Properly handles envelopes and DSP echo.
  • No subsong support yet.
« Last Edit: 5 Feb '16 - 08:04 by krashan »

Fraggie

  • Posts: 713
Re: DigiBooster 2/3 plugin
« Reply #1 on: 31 Oct '14 - 15:50 »
Yay! Thanks! :D

piovrauz

  • Posts: 1020
Re: DigiBooster 2/3 plugin
« Reply #2 on: 31 Oct '14 - 16:40 »
Thanks. btw, is this suppose to support synthetic samples or not? I suppose it's not, right?

Ian @ un4seen

  • Administrator
  • Posts: 26145
Re: DigiBooster 2/3 plugin
« Reply #3 on: 31 Oct '14 - 17:04 »
Nice! A link has now been added on the XMPlay webpage.

I noticed a couple of things that will make it hard/impossible for some people to use the plugin, but which I think should be fairly easy to fix. The plugin appears to have been built with Visual C++ 2012 and is dynamically linked with the runtime library (MSVCR110.DLL). I don't suppose the plugin actually uses the runtime library very much, so perhaps it could be linked statically to avoid that dependency without adding too much bloatage? Also, it isn't currently XP compatible, but that is possible by switching to the "v110_xp" toolset, as described here...

   http://blogs.msdn.com/b/vcblog/archive/2012/10/08/windows-xp-targeting-with-c-in-visual-studio-2012.aspx

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #4 on: 31 Oct '14 - 17:29 »
Thanks. btw, is this suppose to support synthetic samples or not? I suppose it's not, right?
DigiBooster does not use synthetic samples, only wavetables.
« Last Edit: 31 Oct '14 - 17:41 by krashan »

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #5 on: 31 Oct '14 - 17:40 »
The plugin appears to have been built with Visual C++ 2012 and is dynamically linked with the runtime library (MSVCR110.DLL). I don't suppose the plugin actually uses the runtime library very much, so perhaps it could be linked statically
Yes, I have used Visual C++ 2012 Express. The plugin uses only malloc(), calloc(), free(), sprintf() and memcpy(). I will try to link it statically and also use XP targetting for the next version. As I do not have a Windows machine at home, it can be done on Monday.

All these problems are probably caused by my minimal experience in Windows programming. While I write code for 20 years, all it is mostly done on Amiga/MorphOS. Then your help is very appreciated :).

piovrauz

  • Posts: 1020
Re: DigiBooster 2/3 plugin
« Reply #6 on: 31 Oct '14 - 18:15 »
Small question: I find the volume level of my dbm tracks very low. Is it possible to put a boost somewhere (like other plugin do)?
Just asking, if it's too much work nevermind.

Also, I noticed that the loops doesn't seem to work: I mean, I set XMPlay to loop the file, but it just goes to the next one...
Is it related to the plugin? (I can live with no seeking, np there)
« Last Edit: 31 Oct '14 - 18:23 by piovrauz »

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #7 on: 31 Oct '14 - 18:48 »
As for volume level, that's true, it is currently at 0 dB, which is usually too low, especially for modules with many tracks. The replayer has boost function in the API, it operates on internal mixer, so using it would give better result than amplifying the output. The problem is, each module has different optimal replay gain level, and the level is not stored in a module.

As there is no example of module replayer plugin in the SDK, I've based on FLAC plugin example. Then I don't know how to expose this boost thing to the user. Alternatively I can just pre-fly the whole module and calculate + apply optimal boost automatically. Any modern (not older than 5 years) x86 processor renders even most complex DBM modules not slower than 200x realtime, so delay would not be noticeable.

A similar approach can be used for seeking. Seeking by calculating pattern/row position and playing from there is not precise, as there may be instruments, which should still sound at the given position, but are triggered earlier. Then the only true seeking is achieved by silently rendering the module from the start each time (maybe with some buffer to make "knob sliding" smoother). Still there is also a problem how to calculate playback time for modules, which are looped internally using tracker effects (like Bxx and Dxx), in theory the play time is infinite in such case.

The last thing is looping. I've seen different loop flags in the SDK, but have not studied it yet. I would be thankful for any advices, how it should be properly done in the code.

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #8 on: 3 Nov '14 - 09:32 »
Version 0.2:

http://digibooster.eu/media/xmp-digi3-0.2.zip

  • Statically linked with the standard library. No more requires MSVC Runtime Redistributable. The plugin is now 90 kB instead of 30, but well, such is life...
  • Built with Windows XP enabled toolchain. Tested on Windows XP.

Ian @ un4seen

  • Administrator
  • Posts: 26145
Re: DigiBooster 2/3 plugin
« Reply #9 on: 3 Nov '14 - 17:00 »
As for volume level, that's true, it is currently at 0 dB, which is usually too low, especially for modules with many tracks. The replayer has boost function in the API, it operates on internal mixer, so using it would give better result than amplifying the output. The problem is, each module has different optimal replay gain level, and the level is not stored in a module.

As there is no example of module replayer plugin in the SDK, I've based on FLAC plugin example. Then I don't know how to expose this boost thing to the user.

Additional options can be presented via the plugin's Config function. A little demonstration of doing that can be found in the "flange" DSP plugin example. I have updated that just now to store it's config (in XMPLAY.INI), so you could re-download the plugin SDK to see that.

The last thing is looping. I've seen different loop flags in the SDK, but have not studied it yet. I would be thankful for any advices, how it should be properly done in the code.

If you include XMPIN_FLAG_LOOP in the plugin's flags, then XMPlay will call the plugin's SetPosition function with the XMPIN_POS_LOOP or XMPIN_POS_AUTOLOOP value to request looping or auto-looping. In the auto-looping case, the function should only loop when a loop has been detected, and otherwise return -1. If the time of the loop start position is known, that should be returned, otherwise -2 can be returned to let the time run on.

Btw, I would recommend editing the 1st post whenever a new version is available. It'll save people having to hunt through the thread for the latest version :)

guest

  • Guest
Re: DigiBooster 2/3 plugin
« Reply #10 on: 3 Nov '14 - 19:49 »

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #11 on: 3 Nov '14 - 21:28 »
@guest: It is probably caused by some instrument having sampling rate below 2 kHz. The plugin rejects the module then. I will probably add auto upsampling feature to libdigibooster3 in the future. Anyway I will analyse this module tomorrow.

@Ian: What is the format of string being put to buffer by GetSamples()? I've tried with <sample number as string><tab><sample name><cr>, and all the string null terminated. Seems to work but sometimes I get leftovers from the previous module, like some extra terminator is missing.

@all: Today I have added getting module title, displaying version of module creator program in "General" window, displaying number of tracks, patterns, songs, instruments, samples, volume and panning envelopes in "Message" window, also displaying instrument names works, but with the problem described above. Also working on subsong support, but it needs proper implementation of SetPosition(), also looping support depends on this. Will keep you informed.

Ian @ un4seen

  • Administrator
  • Posts: 26145
Re: DigiBooster 2/3 plugin
« Reply #12 on: 4 Nov '14 - 18:05 »
@Ian: What is the format of string being put to buffer by GetSamples()? I've tried with <sample number as string><tab><sample name><cr>, and all the string null terminated. Seems to work but sometimes I get leftovers from the previous module, like some extra terminator is missing.

That is the correct format for the info window text, but in the case of sample text, it should be terminated with a double-null. Or if you would like to have side by side instrument and sample lists (like XMPlay has for XM/IT files), then you can have 2 null-terminated text blocks, one after the other (double-null at the end of the 1st block just means the 2nd block is empty.

If there's a chance that the text may include tabs or new-lines, then it's best to use the FormatInfoText function to handle it. For example...

Code: [Select]
void WINAPI GetSamples(char *buf)
{
for (int a=0; a<numsamples; a++) {
char samnum[8];
sprintf(samnum, "%03d", a+1);
buf=xmpfmisc->FormatInfoText(buf, samnum, samples[a].name);
}
buf[1]=buf[0]=0; // double-null
}

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #13 on: 6 Nov '14 - 09:23 »
I have just released version 0.3 (use the link in the first post). New features:

  • The plugin properly extracts module title.
  • Version of DigiBooster used to create a module is displayed in the "General" window.
  • The "Message" window displays module statistics (number of songs, tracks, patterns, instruments, samples and envelopes).
  • The "Samples" window displays names of instruments.
  • Configuration window with two features:
    • Optional disabling the plugin for DigiBooster Pro 2.x modules. The reason for this is DigiBooster 3 uses different pitch unit when doing portamento and vibrato. 2.x version relied on Amiga periods for this, DB 3 uses 1/8 semitone units. Then some people complained that some modules sound bad. In my personal opinion, most of modules sound much worse when played with other plugins available. But well, with this option ticked, my plugin recognizes and loads only modules saved with DigiBooster 3.x, leaving 2.x ones for other plugins installed.
    • Pre-amp, aka volume boost. This boosting works inside the internal mixer, before the downmix is scaled to 16 bits. Then it is lossless (as long as there is no overdrive) and introduces no additional quantization noise. Possible overdrive is hard-clipped. The slider works realtime.
  • About window.

TODO:
  • Saving config.
  • Subsong selection.
  • Looping.
  • Optimal pre-amp calculation on demand.
  • Option for automatic module pre-render to set the optimal pre-amp for each module.
« Last Edit: 6 Nov '14 - 09:26 by krashan »

Fraggie

  • Posts: 713
Re: DigiBooster 2/3 plugin
« Reply #14 on: 6 Nov '14 - 13:59 »
Song length detection and seeking, please!...

piovrauz

  • Posts: 1020
Re: DigiBooster 2/3 plugin
« Reply #15 on: 6 Nov '14 - 16:51 »
Possible bug report: if I set the volume boost to 12, after closing and re opening XMPlay the setting is lost.
Is someone else experiencing this?

Also... +1 for seeking ;)

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #16 on: 6 Nov '14 - 17:41 »
if I set the volume boost to 12, after closing and re opening XMPlay the setting is lost.

See the first item of TODO above. ;)

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #17 on: 6 Nov '14 - 17:54 »
As for module time estimation and seeking - there is no good method to do it. There are some fundamental problems:

1. How would you determine the length (playback time) of a module, which is explicitly infinitely looped with Bxx and Dxx effects?

2. Even if we take a module without tempo changes, loops, pattern delays and jumps, so we can convert time to module pattern and row easily, starting playback at some place may give inconsistent results with just playing the module from the start to this place. This is because some instruments may be triggered earlier and should still play at given position. Think also about echo effects.
« Last Edit: 6 Nov '14 - 17:58 by krashan »

piovrauz

  • Posts: 1020
Re: DigiBooster 2/3 plugin
« Reply #18 on: 6 Nov '14 - 18:19 »
Oh! "saving config" was actually that. Great, not a bug, just a missing (for now) feature. And already on the TODO. ;)

About seeking / lenght extimation: isn't that a problem for "normal" modules too?
I mean, I remember I have some infinite looping modules, but XMPlay handles it nicely.

About the reasoning on instrument and effects: true, nothing you can do there, if one seeks in a "sensible" position something may be lost/modified.

Maybe Ian can give you some tips on how it's done in XMPlay, and you can use that as a starting point?
Or better, you could use/read the settings of the looping section in XMPlay? Ian, is that possible?

guest

  • Guest
Re: DigiBooster 2/3 plugin
« Reply #19 on: 6 Nov '14 - 18:28 »

saga

  • Posts: 2764
Re: DigiBooster 2/3 plugin
« Reply #20 on: 6 Nov '14 - 18:45 »
1. How would you determine the length (playback time) of a module, which is explicitly infinitely looped with Bxx and Dxx effects?
It's not like this is an unsolved problem, plenty of other plugins and XMPlay's own module player can do it as well.
To give you a very rough idea of how OpenMPT (and most likely also XMPlay) does it...

- Initialize some bit array which stores one bit for every row of every pattern. Bit set = row has been visited. Initially, all bits are 0.
- Emulate module playback (i.e. without rendering samples and such, since it's not necessary), and for every row that has been visited, set the corresponding bit to 1.
- If a row has been visited before (bit is 1), abort length detection.
- For seeking, extend the above behaviour to also keep track of row times, and as soon as the wanted seek time is reached, stop the emulated playback process and set the "real" player's playback position to the one determined by the emulation.
Now if a module is set to loop endlessly, obviously the reported song length would be the time at which the song starts to loop.

Two things to keep in mind:
- Pattern loops may lead to infinite loops. To avoid this, Keep track of the time of first row of the pattern loop, and when you reach the end of the loop, add the time that has passed since the first row of the loop as many times as the loop count is set to.
- Emulation should probably keep track of any kind of "global" effects such as global volume changes, so that their correct value is set when seeking.

Since, as far as I understand, you are also the author of libdigibooster3, it should be possible for you to implement this stuff directly in the library.

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #21 on: 7 Nov '14 - 07:34 »
@saga: Thank you for these explanations. While not trivial, the task seems to be doable, and in fact it would be better to implement this functionality inside libdigibooster3 and expose through the public API.
« Last Edit: 7 Nov '14 - 07:37 by krashan »

guest

  • Guest
Re: DigiBooster 2/3 plugin
« Reply #22 on: 8 Nov '14 - 20:55 »
ftp://modland.com/pub/modules/Digibooster Pro/Blakkhar/zuckerfrei.dbm
1. Sample names 7, 8, 9, 18 aren't displayed completely.
2. There are clicks eg. at 1:10-1:30.

krashan

  • Posts: 12
Re: DigiBooster 2/3 plugin
« Reply #23 on: 8 Nov '14 - 22:57 »
1. Sample names 7, 8, 9, 18 aren't displayed completely.

Seems that FormatInfoText() function from the XMPlay API filters out texts with characters outside ASCII range. All these samples contain German character "ü". I will probably have to replace FormatInfoText() with custom code. It is also possible that this function expects UTF-8 string, so ISO-1 "ü" is detected as bad encoding.

2. There are clicks eg. at 1:10-1:30

This requires further investigation. It may be a bug in the replayer.

saga

  • Posts: 2764
Re: DigiBooster 2/3 plugin
« Reply #24 on: 8 Nov '14 - 23:12 »
Yes, XMPlay expects UTF-8 strings. You can use WinAPI's MultiByteToWideChar to convert between charsets.