PuavoHard Intro Music Composer sync

category: general [glöplog]

Msx-men uses PuavoHard Intro Music Composer for creating music for 4kb intro. Does anyone know how to sync music with intro effects. Unfortulatelly this tool is not well documented ;(

Any hints or tips will be appreciated very much.

Thank you in advance
i never used it but taking a quick look at
http://www.puavohard.net/php/prod/phpimc/phpimc_v3.4.zip it seems like there is example code on how to play the tracks.

just include it in your framework?!
added on the 2016-07-27 22:55:35 by psenough psenough

Using song in a 4k intro

NOTE: The example songs included in this package are not meant to be used in 4k.
They are too big for 4k intros. Try to use less oscillators and effects in your songs!

You can generate c++ code easily from your song.
Open the song and select file -> export -> c++
A notepad window opens immediately with the exported code inside.
Copy the first part of the code - Defines - into ImcSongDataDefines.h
Save the rest of the file in ImcSongData.cpp

Then you need to add these and the rest of the files into your project.
You can find the needed files from the "cpp" folder.

Add the following into your main cpp file.:
#include "ImcSongApi.h"

And add to your main function:

If you wan't to track the song position, add a global variable:
TImcSongPos songPos;

And add to your main loop:

Link the program with winmm.lib.

That's all. The player plays the song immediately without any precalc.

You may want to see and try ExampleMain.cpp in the "cpp" folder.

seems pretty straight forward, where do you have issues?
added on the 2016-07-27 23:10:20 by psenough psenough
I wrote Windows console application to investigate more TImcSongPos songPos structure. Generally speaking win application in loop shows on the screen values of curTime, curSampleInRow, curRowInPattern, curOrderPos and they always are 0:

songPos.curTime: 0
songPos.curSampleInRow: 0
songPos.curRowInPattern: 0
songPos.curOrderPos: 0
songPos.curTime: 0
songPos.curSampleInRow: 0
songPos.curRowInPattern: 0
songPos.curOrderPos: 0
songPos.curTime: 0
songPos.curSampleInRow: 0
songPos.curRowInPattern: 0

source code:

int main (){


while (songPos.curOrderPos < IMCSONG_LEN)
cout << "songPos.curTime: " << songPos.curTime << endl;
cout << "songPos.curSampleInRow: " << songPos.curSampleInRow << endl;
cout << "songPos.curRowInPattern: " << songPos.curRowInPattern << endl;
cout << "songPos.curOrderPos: " << songPos.curOrderPos << endl;


return 1;
seems like you're missing

And add to your main loop:

that was mentioned on the readme.txt
added on the 2016-07-30 17:32:54 by psenough psenough
@Psenough, you are right. Thank you.
no prob :)
added on the 2016-07-31 00:46:49 by psenough psenough
Does anybody know how to detect beat in music from PIMC? I would like fo flash screen if beat detected. Pseudocode:
if (beatDetected)
There is:

struct TImcSongPos {
int curTime;
int curSampleInRow;
int curRowInPattern;
int curOrderPos;

structure in PHIMC API. Does anybody know how use it for beat detecting?
if you have a tracker format being played you don't really need to keep track of beats, you already have curRowInPattern and curOrderPos. i would suggest using those.
added on the 2016-08-15 23:46:33 by psenough psenough
@Psenough: To be honest I have no clue how to use curRowInPattern and curOrderPos for beat detection (and the whole TImcSongPos). I wrote a simple console application which in loop shows on the screen values of curTime, curSampleInRow, curRowInPattern, curOrderPos. For example (real values from the real PIMC tune):

songPos.curOrderPos: 34, 0x22
songPos.curTime: 69985, 0x11161
songPos.curSampleInRow: 5130,0x140a
songPos.curRowInPattern: 15, 0xf
songPos.curOrderPos: 34, 0x22
songPos.curTime: 70000, 0x11170
songPos.curSampleInRow: 280,0x118
songPos.curRowInPattern: 0, 0x0
songPos.curOrderPos: 35, 0x23

First value is in dec, second in hex. Could you please clarify how use these values for beat detection?

Thank you in advance!
If your song is not completely drunk music, you will typically have your beat on multiples of N, e.g. a beat will appear on every 4th or 8th row typically. So if curRowInPattern is divisible by that number, you are currently on a beat.
Looks like a pattern consists of 16 rows (curRowInPattern wraps from 15 to 0 in your example). curOrderPos increased at the same time, thats your pattern index (going from 34 to 35).
So basically +1 for curRowInPattern means 1/16th beat for song progress.
What psenough meant was you can just use every quater beat as "beat detection". So 0 4 8 and 12 for curRowInPattern would be usual basedrum positions. But only if the song uses it all the time without variance.
If you want a real beat detection either the api needs to provide that or you have to analyze the soundbuffer yourself
added on the 2016-08-17 01:59:49 by gopher gopher
i would expect one of those variables has to be the current row being played...

the tracker player should already be playing the current pattern at a given song bpm (usually a variable set when initializing the player (or loading the song)). so technically each row already is a beat.

never having used puavohard i would guess songPos.curRowInPattern is the variable outputting which row the player is currently playing. and songPos.curOrderPos probably the pattern order currently playing.

so you can do a switch to narrow down what to do on each certain pattern orders. and then inside the active scene check if songPos.curRowInPattern is higher or lower then something to toggle stuff on or off.

the non tracker player way to get your beats is to divide the elapsed time by the bpm of the track and get an integer value out of that which you can do things with. like check if it's higher or lower then some value (to know in which part your demo is at). and compare it against %8 == 0 or %16 == 0. etc (to know when to trigger stuff on beat).

beware of errors due to lack of timer precision and rounding and such.

and read urs's explanation on the other thread, he knows these things better then i do. :)
added on the 2016-08-17 02:06:55 by psenough psenough
i always considered a beat to be the row resolution.

not the bassdrum periodicity, but ok. :)
added on the 2016-08-17 02:11:50 by psenough psenough
Thank you all for explanations! I am trying to investigate more the PHIMC structure's field curSampleInRow. I wrote simple console application which displays on the screen and writes to the file values of all fields of the structure. Tune is really simple: 2 channels of percussion. Please find attached printscreen:


As you can see for 3rd second value E-5 is played on the channel 3. If you look at part of the log file data for 3rd second (secs are in milisconds)

songPos.curTime: 3000, 0xbb8
songPos.curSampleInRow: 12,0xc
songPos.curRowInPattern: 8, 0x8
songPos.curOrderPos: 1, 0x1
songPos.curTime: 3000, 0xbb8
songPos.curSampleInRow: 12,0xc
songPos.curRowInPattern: 8, 0x8
songPos.curOrderPos: 1, 0x1

curTime, curRowInPattern, curOrderPos are the same. That make sense to me, but why values of curRowInPattern are different?

Please find attached the whole log:


There in stated the source code of the PIMC :
pos.curSampleInRow = sample % IMCSONG_ROWLENSAMPLES and #define IMCSONG_ROWLENSAMPLES 5512. Do you know what is curSampleInRow variable? Is it usefull for beat detection or other things?
And nothing?:)
sorry, went on holidays. never used PHIMC in production though, so i can't help you much.

i would assume curRowInPattern would be the current row position the player is currently at. patterns in trackers usually have a certain ammount of rows (usually 64) and the player goes through them one at a time at a certain bpm, triggering whatever samples that are listed there.

not sure what curSampleInRow could be, maybe the audio buffer for the channel? or the id of which sample is playing.

i would just throw the values to the screen somehow (bar chart or something) as the music is playing and figure it out which ones could be usable.
added on the 2016-08-22 17:48:24 by psenough psenough
Some code from ImcSongPlayer.cpp file:

void ImcSongUpdatePos(TImcSongPos & pos) {
pos.curTime = GetTickCount() - songStartTime;
int sample = (441 * pos.curTime) / 10;
int row = sample / IMCSONG_ROWLENSAMPLES;
pos.curOrderPos = row / 16;
pos.curRowInPattern = row & 15;
pos.curSampleInRow = sample % IMCSONG_ROWLENSAMPLES;

Why is value 441 used in line int sample = (441 * pos.curTime) / 10?
44.1 khz samplerate