Tempo Control in System Exclusive Messages (Style)

Started by chikitin, January 16, 2019, 07:34:18 PM

Previous topic - Next topic

chikitin

Hi,

I am planning to write a little program to help me with making styles in my PSR-A3000. The Tempo Control has the following format.

F0 43 7E 01 t4 t3 t2 t1 F7, where t1-4 are showing in attached table. Are there used to set the tempos for different style parts? say MainA, .... ? what are they used for?

Thank you,

CS


[attachment deleted by admin]

SeaGtGruff

No, they would be four parts of a single number, although I don't know without looking into it what the format is. I do know that some Sy*** messages of this sort might use only the low nibble of each data byte, so that a 4-byte argument would end up being interpreted as a 2-byte or 16-bit value:

t1 t2 t3 t4 = xa xb xc xd = ab cd

where the "x" nibbles are ignored. That's because each t1 t2 t3 t4 byte can't exceed a value of 127. But I don't know if the tempo arguments work that way.

Edit: Sorry, I guess I should have said t4 t3 t2 t1 rather than the other way around. The t1 byte is the least-significant byte (or nibble), whereas the t4 byte is the most-significant byte/nibble.

tyrosaurus

Hi CS,

Some years ago I looked into the Sy*** tempo control for styles on my Tyros4.

As a result I produced a table showing the Sy*** message for all tempos from 5 to 500 BPM.

When I sent the relevant message to my T4 over MIDI from my computer using MIDI-Ox, the tempo on the keyboard changed as expected.

The Sy*** message format for your A3000 appears to be the same as the T4 so I have attached the table if it is of any interest to you.


Regards

Ian

[attachment deleted by admin]

CrzyCDN

This is the routine I use in visual Basic.

Dim MyTempo As Integer
Dim xTem1 As Long
Dim xTem2 As Long
Dim xTem3 As Long
Dim TotalTempo As Long
    MyTempo = RequiredTempoHere
    TotalTempo = Int(60000000 / MyTempo)
    xTem1 = TotalTempo \ (2 ^ 14) And 127  '14 bit shift
    xTem2 = TotalTempo \ (2 ^ 7) And 127   ' 7 bit shift
    xTem3 = TotalTempo And 127
'---------- tempo sysx
SysxBuffer = Chr$(&HF0) & Chr$(&H43) & Chr$(&H7E) & Chr$(&H1) & Chr$(&H0) &  Chr$(xTem1) & Chr$(xTem2) & Chr$(xTem3) & Chr$(&HF7)

Note above ... "\" is integer divide.

Regards  Ted

Tyros5Mad

Quote from: tyrosaurus on January 17, 2019, 05:15:29 AM
Hi CS,

Some years ago I looked into the Sy*** tempo control for styles on my Tyros4.

As a result I produced a table showing the Sy*** message for all tempos from 5 to 500 BPM.

When I sent the relevant message to my T4 over MIDI from my computer using MIDI-Ox, the tempo on the keyboard changed as expected.

The Sy*** message format for your A3000 appears to be the same as the T4 so I have attached the table if it is of any interest to you.


Regards

Ian

Hey thanks for this Ian. This is exactly what I have been looking for to program tempo control properly in my Midi Maker program.

Regards, Richard

SeaGtGruff

The code Ted posted shows that the Tempo argument in Yamaha's Style Tempo Sy*** message must be computed the same way as the Tempo argument in a Standard MIDI File's Tempo Meta Event. 8)

Tyros5Mad

Quote from: SeaGtGruff on January 17, 2019, 05:45:04 PM
The code Ted posted shows that the Tempo argument in Yamaha's Style Tempo Sy*** message must be computed the same way as the Tempo argument in a Standard MIDI File's Tempo Meta Event. 8)

I found that, although I am doing the TempoMetaMidiEvent, the Genos does not change the tempo until I send the sy*** tempo control message. I struggled with the format of that message so thanks to Ian for the table and also thanks to Ted for the VB code. I understand now how the calc is done. That can easily be converted to C# so I am grateful to both of them.

Regards, Richard

chikitin

Thank you Michael as always.

Ian thank you very much for the table of the Sy*** message.
Also Ted, thank you very much for sharing your code with me!

Best,
CS

chikitin

Quote from: CrzyCDN on January 17, 2019, 06:20:40 AM

Dim MyTempo As Integer
Dim xTem1 As Long
Dim xTem2 As Long
Dim xTem3 As Long
Dim TotalTempo As Long
   
SysxBuffer = Chr$(&HF0) & Chr$(&H43) & Chr$(&H7E) & Chr$(&H1) & Chr$(&H0) &  Chr$(xTem1) & Chr$(xTem2) & Chr$(xTem3) & Chr$(&HF7)


Hi Ted,

If I understand your routing correctly ( I have never done VB), we have a function with single input: MyTempo and single output: SysxBuffer. The rest of the variables are auxiliary/helper variables.



I tried to convert your code to JavaScript.

function hex(yourNumber) {
    hexString = yourNumber.toString(16);
    if (hexString.length % 2) {
        hexString = '0' + hexString;
    }
    return hexString;
}
function tempoPSR(MyTempo) {
    var MyTempo, xTem1, xTem2, xTem3, TotalTempo;
    TotalTempo = Math.floor(60000000 / MyTempo);
    xTem1 = Math.floor(TotalTempo / (2 ^ 14)) & 127;  //14 bit shift
    xTem2 = Math.floor(TotalTempo / (2 ^ 7)) & 127;   // 7 bit shift
    xTem3 = TotalTempo & 127;
    //---------- tempo sy***
    return [hex(0xF0), hex(0x43), hex(0x7E), hex(0x1), hex(0x0), hex(xTem1), hex(xTem2), hex(xTem3), hex(0xF7)].join(" ");
}
console.log(tempoPSR(5));


In my case, 5 BMP I get: f0 43 7e 01 00 40 00 00 f7

This is different from the one in the Ian's table, that is F0 43 7E 01 05 5C 36 00 F7. What am I doing wrong please?

SeaGtGruff

Quote from: RichardL on January 17, 2019, 06:29:06 PM
I found that, although I am doing the TempoMetaMidiEvent, the Genos does not change the tempo until I send the sy*** tempo control message.

Meta Events can only be used in MIDI files, such as song files or style files, so you can't send a Tempo Meta Event to a keyboard (you can try, but it won't work). And I think the Tempo Meta Event, taken in conjunction with other settings— the PPQN and maybe the Time Signature, I think— set the NIDI clock rate and how many ticks correspond to a beat (which is usually but not always a quarter note), so it affects the MIDI playback speed but probably not the system Tempo setting of the keyboard. That's why you need to use the Yamaha Style Sy*** message to change the actual system Tempo.

chikitin

Quote from: SeaGtGruff on January 16, 2019, 09:16:26 PM
No, they would be four parts of a single number, although I don't know without looking into it what the format is. I do know that some Sy*** messages of this sort might use only the low nibble of each data byte, so that a 4-byte argument would end up being interpreted as a 2-byte or 16-bit value:

t1 t2 t3 t4 = xa xb xc xd = ab cd

where the "x" nibbles are ignored. That's because each t1 t2 t3 t4 byte can't exceed a value of 127. But I don't know if the tempo arguments work that way.

Edit: Sorry, I guess I should have said t4 t3 t2 t1 rather than the other way around. The t1 byte is the least-significant byte (or nibble), whereas the t4 byte is the most-significant byte/nibble.

Michael,

How does: F0 43 7E 01 05 5C 36 00 F7 translates to 5? according to your notation: dcba = 06C4.

SeaGtGruff

I said that SOME Sy*** messages use arguments where only the low nibbles are used, but that I did NOT know whether this was the case with the Tempo message.

Based on the values that Ian posted, it is evidently NOT how the Tempo arguments work. Rather, it appears that they use all 7 of the data bits in each byte (there are 8 bits in all, but the highest bit is used as a "status flag" rather than as a data bit).

The code that Richard posted shows the number 60000000 being divided by the Tempo argument (after the separate arguments have had their data bits combined into a single numeric value), which as I recall is how Tempo is computed for a MIDI file.

But I haven't reviewed the computation for the Tempo Meta Event and compared its results to the values which Ian posted. I was going to do that tonight-- I've just started to create a spreadsheet for that and had just pulled up this thread to grab the list that Ian had posted when I saw your question-- so I'll post again after I've finished looking into it. :)

EDIT: One example of a Yamaha Sy*** message which uses only the lower nibbles is the "MIDI Tuning" message, which despite its name is actually a Yamaha Sy*** message, not the General MIDI "Master Fine Tuning" message. The one I'm referring to is not the XG Fine Tuning message, but an older Sy*** message that Yamaha used with their TG100 tone generator and still use with many of their keyboards (such as the PSR-E models). I was recently experimenting with that message on my keyboards, so I happened to have the "low nibbles only" data format fresh in my mind when I posted earlier.

Tyros5Mad

Converting vb code to another language is not always straightforward. I needed to convert Ted's code to C# and it looked easy at first but I ran into trouble with the two lines:

        xTem1 = TotalTempo \ (2 ^ 14) And 127  '14 bit shift
        xTem2 = TotalTempo \ (2 ^ 7) And 127   ' 7 bit shift

The (2 ^ 14) is Math.Pow(2,14) in C# but *** the result is a double. it took a bit of "googling" to find how to get the result to an integer. here is the partial c# code that does the job


    int MyTempo = 80;
    int xTem1;
    int xTem2;
    int xTem3;
    int TotalTempo;

    TotalTempo = 60000000 / MyTempo;
    xTem1 = TotalTempo / (int)(Math.Pow(2, 14)) & 127;  // 14 bit shift
    xTem2 = TotalTempo / (int)(Math.Pow(2, 7)) & 127;   // 7 bit shift
    xTem3 = TotalTempo & 127;


Maybe that will help with the JavaScript, which is a lot like c#. Maybe it will not. I do not know JS well.

Regards, Richard

SeaGtGruff

I threw together a spreadsheet that takes the numbers Ian posted and converts the four bytes of the argument into a single decimal value. However, the decimal value is not the Tempo; rather, you must divide 60000000 by the decimal value-- and take the integer portion of the result-- to get the Tempo. So it agrees with the code that Richard posted.

chikitin

Quote from: RichardL on January 18, 2019, 12:48:37 AM
Converting vb code to another language is not always straightforward. I needed to convert Ted's code to C# and it looked easy at first but I ran into trouble with the two lines:

        xTem1 = TotalTempo \ (2 ^ 14) And 127  '14 bit shift
        xTem2 = TotalTempo \ (2 ^ 7) And 127   ' 7 bit shift

The (2 ^ 14) is Math.Pow(2,14) in C# but *** the result is a double. it took a bit of "googling" to find how to get the result to an integer. here is the partial c# code that does the job


    int MyTempo = 80;
    int xTem1;
    int xTem2;
    int xTem3;
    int TotalTempo;

    TotalTempo = 60000000 / MyTempo;
    xTem1 = TotalTempo / (int)(Math.Pow(2, 14)) & 127;  // 14 bit shift
    xTem2 = TotalTempo / (int)(Math.Pow(2, 7)) & 127;   // 7 bit shift
    xTem3 = TotalTempo & 127;


Maybe that will help with the Java, which is a lot like c#. Maybe it will not. I do not know Java well.

Regards, Richard


Perfect! Thank you Richard and Machael .I works perfectly now. Here is my JS code which is in syntax pretty similar to Java and C#!


==== tempo.js ====
function hex(yourNumber) {
    hexString = yourNumber.toString(16);
    if (hexString.length % 2) {
        hexString = '0' + hexString;
    }
    return hexString;
}
function tempoPSR(MyTempo) {
    var MyTempo, xTem1, xTem2, xTem3, TotalTempo;
    TotalTempo = Math.floor(60000000 / MyTempo);
    xTem1 = Math.floor(TotalTempo / Math.pow(2 , 14)) & 127;  //14 bit shift
    xTem2 = Math.floor(TotalTempo /  Math.pow(2 , 7)) & 127;   // 7 bit shift
    xTem3 = TotalTempo & 127;
    //---------- tempo sy***
    return [hex(0xF0), hex(0x43), hex(0x7E), hex(0x1), hex(0x0), hex(xTem1), hex(xTem2), hex(xTem3), hex(0xF7)].join(" ");
}
console.log(5, tempoPSR(5));
console.log(120, tempoPSR(120));
console.log(120.1, tempoPSR(120.1));
   
When I run it:

$ node tempo.js
5       'f0 43 7e 01 00 5c 36 00 f7'
120    'f0 43 7e 01 00 1e 42 20 f7'
120.1 'f0 43 7e 01 00 1e 3e 7f f7'


SeaGtGruff

I'm curious whether a fractional (decimal) value will work, since the keyboard lets you set only integer tempos. I would recommend trying something like 60, 60.5, and 61. Set the tempo to 60 and let the style play for a minute, which should be long enough to verify that the beats stay synchronized with whole seconds. Then set the tempo to 60.5 and let the style play for another minute. You should be able to tell by the end of a minute whether the beats and bars continue to be synchronized with whole seconds. And finally, set the tempo to 61 and let the style play for another minute. Hopefully you will be able to tell whether the beat has sped up again.

Normanfernandez

Quote from: SeaGtGruff on January 18, 2019, 08:55:51 AM
I'm curious whether a fractional (decimal) value will work, since the keyboard lets you set only integer tempos. I would recommend trying something like 60, 60.5, and 61. Set the tempo to 60 and let the style play for a minute, which should be long enough to verify that the beats stay synchronized with whole seconds. Then set the tempo to 60.5 and let the style play for another minute. You should be able to tell by the end of a minute whether the beats and bars continue to be synchronized with whole seconds. And finally, set the tempo to 61 and let the style play for another minute. Hopefully you will be able to tell whether the beat has sped up again.
To create this tempo change,
Is Mix Master an option? 

I'm still have a tough time understanding System Exclusive Messages And System Messages.

Is it possible to have a Message.
Where you are able to Automatically change a Main Variation?
Regards Norman.
Norman Fernandez Keyboardplayer
https://www.youtube.com/channel/UCngm8h5k5NmKnowJpkxlDBQ

PSR S770 - Roland FP 30 - PSR 280
Cubase - Kontakt6

chikitin

Quote from: SeaGtGruff on January 18, 2019, 08:55:51 AM
.... Set the tempo to 60 and let the style play for a minute, which should be long enough to verify that the beats stay synchronized with whole seconds. ...

Michael,

How do you do this please?

I was planning to send these messages from Cubase and have PSR clock to External.

tyrosaurus

Hi CS,

Out of interest I have just sent the Sy*** message that you posted for 120.1 BPM as calculated by your routine to my Tyros4, and the tempo display changed to 120.

I haven't tried to time the set tempo accurately since I am not interested in such small changes! I wonder why you are?

Your calculated message for tempo 5 BPM changes the tempo on the keyboard display to 40 BPM!  I was not surprised about this because for tempos below 29 BPM, the first value in the 4 tempo data values changes from '00', but your routine does not seem to incorporate this. 

My T4 sends the tempo Sy*** message out over MIDI when you change the tempo using the keyboard buttons, and I can see that the correct message for tempo 5 BPM is actually  'F0 43 7E 01 05 5C 36 00 F7' (which is as shown in my table).  Again I am not particularly interested in such slow tempos, so assuming your calculated values above 28 BPM are all correct, this would be fine for me!


Regards

Ian

murrayb

Hi:

The beauty of computer math is that it can be expressed in a number of different ways.  The code below is the VB routine I use in YRM to send tempo changes to the keyboard in the Style Audition part of the Edit screen.  Very simple and straight forward, hope it's useful to others. 

        Dim t0 As Long = 60000000 / (Tempo.Value / 4)
        Dim t1 As Integer = Int(t0 / 65536)
        Dim t2 As Integer = Int((t0 Mod 65536) / 512)
        Dim t3 As Integer = Int((t0 - ((65536 * t1) + (t2 * 512))) / 4)
        Dim txtmsg As String = "F0437E0100" & shex(t1) & shex(t2) & shex(t3) & "F7"


The function for shex that solves the lead "0" problem Ian mentioned:


Function shex(ByVal dd As Integer) As String
        Dim hexout As String
        If dd > 15 Then
            hexout = Hex(dd)
        Else
            hexout = "0" & Hex(dd)
        End If
        Return hexout
    End Function

Murray
One can do without most things, but not without the pleasure of music.

Check out my Registration Manager at:  http://psrtutorial.com/util/best.html

SeaGtGruff

The problem in the code is that the leading byte— what would be t4 in Yamaha's description— is being hard coded to always be 00. You need all four bytes of the argument— t4, t3, t2, and t1. I can't type it out on my iPad, but later I'll post the corrected code from my computer if you haven't already fixed it.

SeaGtGruff

Quote from: chikitin on January 18, 2019, 08:24:09 AM==== tempo.js ====

Following is my correction to your code. I added comments to indicate my changes but you can remove those if you prefer! :)

function hex(yourNumber) {
    hexString = yourNumber.toString(16);
    if (hexString.length % 2) {
        hexString = '0' + hexString;
    }
    return hexString;
}
function tempoPSR(MyTempo) {
    var MyTempo, xTem1, xTem2, xTem3, xTem4, TotalTempo;  // added xTem4
    TotalTempo = Math.floor(60000000 / MyTempo);
    xTem4 = Math.floor(TotalTempo / Math.pow(2, 21)) & 127;   //21 bit shift -- added this line
    xTem3 = Math.floor(TotalTempo / Math.pow(2 , 14)) & 127;  //14 bit shift -- changed xTem1 to xTem3 so they'll be in the order Yamaha used
    xTem2 = Math.floor(TotalTempo / Math.pow(2 , 7)) & 127;    // 7 bit shift
    xTem1 = TotalTempo & 127;  // changed xTem3 to xTem1
    //---------- tempo sy***
    return [hex(0xF0), hex(0x43), hex(0x7E), hex(0x1), hex(xTem4), hex(xTem3), hex(xTem2), hex(xTem1), hex(0xF7)].join(" ");
    // changed hex(0x0) to hex(xTem4), swapped xTem1 and xTem3 to be in the order Yamaha used -- T4, t3, t2, t1
}

SeaGtGruff

Quote from: Normanfernandez on January 18, 2019, 09:18:19 AMTo create this tempo change,
Is Mix Master an option?

Yes, but you'd be inserting it into a song file (SMF) or style file (SFF).

Quote from: Normanfernandez on January 18, 2019, 09:18:19 AMI'm still have a tough time understanding System Exclusive Messages And System Messages.

It's not surprising that Sy*** messages are so confusing to understand, due to the way Yamaha generally presents the information about the pertinent addresses and data arguments in separate tables that are grouped in different sections of the documents. It's like the information you need is scattered to the winds and in order to learn how to write a Sy*** message that does a certain thing you must first go hunt down its various pieces so you can put them together. It all makes sense once you understand the way the information is organized, but you almost need to take a course on how to properly read and use the documentation!

Quote from: Normanfernandez on January 18, 2019, 09:18:19 AMIs it possible to have a Message.
Where you are able to Automatically change a Main Variation?
Regards Norman.

Yes, but it depends on what you mean exactly.

Yamaha has Sequencer-Specific Meta Events that they record inside the User Songs for certain models, which record things like the Style Number, Style Section, and Style Chord. These messages are used on the PSR-E models (among others) to record the Auto Accompaniment track of a User Song. I'm not sure whether they'd work on a PSR-S model, but I don't see why not. Note that Meta Events cannot be transmitted to a keyboard; they can only be used inside a MIDI file, so you could create a MIDI song file that selects a specific style, selects the section and variation you want to start with, changes the chords at the desired times to create a particular chord progression, and switches to a different section or variation as desired.

Yamaha also has Style System Exclusive messages that can be used to turn a particular style section on or off. These messages can be transmitted to a keyboard, so you would normally use them to control the style playback from an external source such as a DAW.

chikitin

Quote from: SeaGtGruff on January 18, 2019, 05:22:54 PM
Following is my correction to your code. I added comments to indicate my changes but you can remove those if you prefer! :)
....

Michael, not sure why my code returned table the same as the table provided by Ian!

chikitin

Quote from: SeaGtGruff on January 18, 2019, 06:15:23 PM
Yes, but you'd be inserting it into a song file (SMF) or style file (SFF).

----, but you almost need to take a course on how to properly read and use the documentation!

Yes, but it depends on what you mean exactly.

-----

A while ago I requested Yamaha the documentation on XG and XF format. They said, they will not make it public.

SeaGtGruff

They did make it public a couple of decades ago, so I don't know why they won't do it now. Go to Jorgen's site and look under the documentation there. I think the last/latest version was v2.00, from 2001 if I remember correctly.

However, much of that same information is still available now in slightly more condensed form (tables without any descriptive text) in the Data List of your particular model.

SeaGtGruff

Quote from: chikitin on January 18, 2019, 07:49:18 PMMichael, not sure why my code returned table the same as the table provided by Ian!

It was fine for all tempos except the ones where the fourth (most significant) byte was non-zero. The correction I made was just to ensure that the fourth byte won't be hard-coded to be a zero.

The other change I made— swapping the xTem1 and xTem3 variables— is purely cosmetic, because the actual output isn't changed, just the order in which the variables are used.

Tyros5Mad

We can accomplish anything when we work together. This discussion is a great example of this.

Regards, Richard

Normanfernandez

Quote from: RichardL on January 18, 2019, 10:44:43 PM
We can accomplish anything when we work together. This discussion is a great example of this.

Regards, Richard
I totally agree.
Also new ideas are formed. 

I'm still giving my best to Understand System Messages.

I've Understood Control Changes well. 
Regards Norman!
Norman Fernandez Keyboardplayer
https://www.youtube.com/channel/UCngm8h5k5NmKnowJpkxlDBQ

PSR S770 - Roland FP 30 - PSR 280
Cubase - Kontakt6

chikitin

I do agree with Richard and Norman.

For system messages, I'd say you need to have software or hardware controller to try different things. But even if you have those, Yamaha and other companies ( due to business and money!) impose many limitations ( such as enciphering/encrypting message, lack of documentation, etc) that sometimes gets really frustrating dealing with system messages and move you away from music creation.

If some folks start to make reliable or functional open-source Hardware controllers and synth, I will buy them

https://www.oshwa.org/2019/01/05/oshwa-supports-design-patent-clarity-in-amicus-brief/
http://www.synthanatomy.com/2018/08/otto-open-source-hardware-synthesizer-op-1.html