OT: Helping WordBuilder cope with tempo changes

If you use the EastWest Symphonic Choirs or Hollywood Choirs, you may already know that WordBuilder can become unstable when faced with too many or too extreme tempo changes. It can begin to mispronounce syllables or even cause the notes and syllables to get out of synch. If your goal is to create an audio recording of WordBuilder singing a piece with substantial tempo changes, I have written a program that can help keep WordBuilder from becoming unstable.

I used this program to create my video of The Shepherds’ Farewell by Hector Berlioz. In my rendition of this piece, the tempo is almost constantly speeding up or slowing down, so the MIDI file exported from the original project had over 450 tempo changes. When WordBuilder tried to sing the original project with the lyrics, the notes and syllables got out of synch before the end of the first verse.

Description of the program

My program takes a MIDI file with any number of tempo changes and converts it into a MIDI file with a fixed tempo in which the notes are no longer related to measures and beats but start and end at the same elapsed times (to the nearest millisecond) as they did before. After the conversion, WordBuilder should be able to sing the lyrics without becoming unstable because it no longer encounters any tempo changes.

Since Cubase and Dorico use 480 ticks per quarter note, at a fixed tempo of 125 quarter notes per minute, each tick lasts one millisecond, each quarter note lasts 480 milliseconds, one measure in 5/4 time lasts 2.4 seconds and 25 measures last one minute.

How to use the program

MIDI files are stored in a compact binary form which makes them more difficult to modify than text files. To simplify the implementation of my program called adjtime, I use the utilities midicsv and csvmidi to convert MIDI files to and from text files in the comma-separated value (CSV) format.

To use adjtime, start by exporting a MIDI file named src.mid from the source program. It is assumed that src.mid specifies a time signature and an initial tempo at the beginning of the file. Now execute the following sequence of commands:

midicsv src.mid src.txt
adjtime < src.txt > dst.txt
csvmidi dst.txt dst.mid

Finally, import dst.mid into the destination program, which is assumed to use 480 ticks per quarter note.

C source code for the program

I am only providing the source code for my program because I’m not sure the Dorico team would want me to post a link to an executable program which might be capable of doing something malicious.

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct tempo {
    struct tempo *link;
    long tempo;
    long ticks;
    long time;
} tempo_t;

char Buffer[BUFSIZ];
int Div;
tempo_t Head = { &Head, 0, LONG_MAX, LONG_MAX };
tempo_t *Node = &Head;
char *Ptr;

void error(char *str)
    fputs(str, stderr);
    fputc('\n', stderr);

long gettime(long ticks)
    if (ticks == 0)
        return 0;
    while (ticks > Node->link->ticks)
        Node = Node->link;
    return (double) (ticks - Node->ticks) / Div * Node->tempo + Node->time + 0.5;

int main(void)
    char *ptr;
    long ticks;
    long time;
    int track;

    while (gets(Buffer) != NULL) {
        track = atoi(Buffer);
        ptr = strchr(Buffer, ',') + 1;
        ticks = atol(ptr);
        time = gettime(ticks);
        Ptr = strchr(ptr, ',') + 1;
        if (strstr(Ptr, "Header") != NULL) {
            ptr = strrchr(Buffer, ',') + 1;
            Div = atoi(ptr);
            strcpy(ptr, " 480");
        else if (strstr(Ptr, "Time_signature") != NULL) {
            if (ticks != 0)
            ptr = strchr(Ptr, ',') + 1;
            strcpy(ptr, " 5, 2, 24, 8");
        else if (strstr(Ptr, "Tempo") != NULL) {
            ptr = strchr(Ptr, ',') + 1;
            Node = Node->link = malloc(sizeof(tempo_t));
            if (Node == NULL)
                error("insufficient memory");
            Node->link = &Head;
            Node->tempo = atol(ptr);
            Node->ticks = ticks;
            Node->time = time;
            if (ticks != 0)
            strcpy(ptr, " 480000");
        else if (strstr(Ptr, "End_track") != NULL)
            Node = &Head;
        printf("%d, %ld,%s\n", track, (time + 500L) / 1000L, Ptr);
    return EXIT_SUCCESS;

For Windows users, the webpage for midicsv and csvmidi contains a link to a zip file containing executable programs for these utilities. For Mac users, this webpage contains a link to a gzip-compressed tar file containing the C source code and a makefile for these utilities.


Hello @johnkprice,
Thanks for your share!

Are you using Play or Opus?


Since I haven’t purchased anything from EastWest since Opus was introduced, I don’t have a license to use it, so I’m still using Play.

it’s an interesting idea, John --thanks for this. I used to have problems in Sibelius with text synchronization in connection with tempo changes but never in Dorico (although I don’t mess around with the tempi more than necessary). I’ve actually just converted 6 Sib files to Dorico and have one more left. Most were changed to Hollywood Choirs which is far easier to manage and I tend to now reserve SC for fairy-tales or similar works where solos are actually implied (but of course impossible as no-one has developed one) and obviously the two thus far which use children’s choirs.

I’d be interested initially in seeing the Dorico original if possible of your work – obviously with the Votox text file so I can see how it works on my system with both choirs. If it struggles then I’d try to see if I can follow your little app.

Opus by the way I find works less well with Hollywood Choirs in case anyone already has or is thinking of getting these.

After I realized that I could not record a video of Dorico playing my rendition of The Shepherds’ Farewell because of WordBuilder’s instability, I deleted the original Dorico project and developed the final version of my rendition from start to finish in a digital audio workstation. I might be able to reconstruct the Dorico project using a MIDI file exported from my DAW, but that will take some time.

I assumed you still had the Dorico original – please don’t go to any trouble unless you really want to for your own purposes.