Music generation creates a new piece by extending musical events learned from existing music. In the sequence-based approach, a trained Transformer takes a short prompt of indexed events, predicts what comes next, and repeatedly appends its predictions. The resulting indexes can be converted to a MIDI file. section 14.4.2 section 14.5
The representation determines the task. MuseGAN treats music as a multidimensional object and generates a complete piece for a critic to evaluate. A music Transformer instead treats a performance as a sequence, much like text generation, so it can continue a supplied beginning. section 13.0 section 13.1
To generate a continuation with the Transformer:
- Encode MIDI as indexed events. Note-on, note-off, time-shift, and velocity events capture what is played, when it changes, and how forcefully it is played. section 14.1
- Start with a prompt—for example, the first 250 events of a test performance. Feed its indexes to the trained model. section 14.4.2
- Predict the next event, sample an index, append it, and repeat until the requested sequence length is reached. Decode the sequence to MIDI for playback. section 14.4.2
A 1,000-event continuation
Save the first 250 events of a test piece as prompt.midi, encode that file, and pass its indexes to sample(prompt, seq_length=1000). Decode the returned indexes as musicTrans.midi. The 1,000-event result includes the prompt as well as the generated continuation; changing temperature to 1.5 provides a second version to compare. section 14.4.2
Listing 14.7 A sample() function in music generation
softmax=torch.nn.Softmax(dim=-1)
def sample(prompt,seq_length=1000,temperature=1):
gen_seq=torch.full((1,seq_length),389,dtype=torch.long).to(device)
idx=len(prompt)
gen_seq[..., :idx]=prompt.type(torch.long).to(device)
while(idx < seq_length): #1
y=softmax(model(gen_seq[..., :idx])/temperature)[...,:388] #2
probs=y[:, idx-1, :]
distrib=torch.distributions.categorical.Categorical(probs=probs)
next_token=distrib.sample() #3
gen_seq[:, idx]=next_token
idx+=1
return gen_seq[:, :idx] #4
The sample() listing shows the generation loop: it copies the prompt into an output tensor, applies softmax to temperature-scaled model predictions, samples the next event, and appends it. It excludes the extra output position before sampling from the 388 event indexes. section 14.4.2
Temperature adjusts the diversity of the continuation. The example uses temperature alone rather than top-K sampling, keeping the generation loop focused on next-event prediction. section 14.4.2
