Go Down

Topic: Implementing MIDI Control Change for “Tsunami Wav Trigger”? (Read 832 times) previous topic - next topic

142victoria

I have a "Tsunami Wav Trigger" working with a modified example Arduino "MIDI note player" sketch, this has been modified so the MIDI Bank Number is changed by using the MIDI Program Change message.
The "Tsunami User Guide - robertsonics" says that the board responds to Controller messages for real-time control of attack and release times. Using  CC#73: Attack Time (0 - 2000ms) and CC#72: Release Time (0 - 2000ms).
I wish to implement attack and release to all the noteOn and noteOff commands so the volume of note will ramp up or down over a specified time.
Can you please help me with my code? I attach a copy below.

Code: [Select]
#include
void setup() {
  // Set MIDI baud rate:
  Serial.begin(31250);

}
int CurrentMidiBank = 1;
int CurrentMidiChannel= 0;

void loop() {

  // Play notes in banks 0, 1, 2 and 3
  // (all on channel 0)
  //
  for( int bank= 0; bank < 4; bank ++ )
  {
    CurrentMidiBank= bank;
    midiBank( CurrentMidiChannel, CurrentMidiBank );

    // play notes from G-3 (0x43) to G-4 (0x4F):
    // for (int note = 0x1E; note < 0x5A; note ++)
    for (int note = 0x43; note < 0x4F; note ++)
    {
      noteOn( CurrentMidiChannel, note, 0x45);
      delay(500);

      noteOff( CurrentMidiChannel, note, 0x00);
      delay(500);   
    }
 
    delay( 1500 );
  } 
}
// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:
// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:
// Send a MIDI note-off message.
void noteOff(byte channel, byte note, byte volume)
{
  midiMsg( (0x80 | channel), note, volume );
}

// Send a general MIDI message
//
void midiMsg(byte cmd, byte data1, byte data2 )
{
    Serial.write(cmd);
    Serial.write(data1);
    Serial.write(data2);
}

MarkT

So you need a control change message for 73 and 72 sent whenever you want to set the relevant
parameters.

The bytes will be
0xBn, 0x48, <release>
0xBn, 0x49, <attack>

For channel n+1.  So channel 1 would be 0xB0,0x48,<release>
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

142victoria

Am I correct that if I want to have a release time of say 40 ms I would put 40 in place of <release> .

For channel n+1.  So channel 1 would be 0xB0,0x48, 40

This I have tried , it compiles but has no effect on fading of notes.
My lack of programming fails me.
Can you please spell it out for me how I set a fade in- out time for the   notes.


Grumpy_Mike

Quote
This I have tried , it compiles but has no effect on fading of notes.
First step is to post your new code so we can see if it is the right place.

Then note the Manual page says:-
Quote
As of firmware v0.60 and above, the following controllers are also supported.

MIDI Controller number 73 (Attack) controls the WAV Trigger note-on attack time (0 to 2000 msecs).

MIDI Controller number 72 (Release) controls the WAV Trigger note-off release time (0 to 2000 msecs).
So what version of the firmware are you using?

And:-
Quote
Am I correct that if I want to have a release time of say 40 ms I would put 40 in place of <release> .
that would be a no then.

As the third parameter of a CC message can only be a number from 0 to 127 and if the maximum release time is 2000ms then to get a 40ms time this would need a value of 2.54, which of course is impossible so use 3. Using a value of 40 will give you just a tad under 630mS. I would try a number of 127 here so it is noticeable.

What sort of Arduino are you using? Do you know this:-
Quote
It is very important to know that this is a 3.3V device, and its inputs - including triggers and serial RX - are not 5V tolerant!

142victoria

Hi, The version of the firmware I am using is ; Tsunami Mono Firmware v1.08m
I am using an Arduino Uno sending serial Midi to the Tsunami opto-isolated MIDI input. Being
opto-isolated, it is fully compatible with regular 5V MIDI circuitry.
The sketch attached plays the notes on the four Banks ,but the release/ attack function has no effect.
Thank you for your help with my code? I attach a copy below.

Code: [Select]
#include
void setup() {
  // Set MIDI baud rate:
  Serial.begin(31250);

}
int attack = 32; // =500ms
int release = 32; // =500ms
int CurrentMidiBank = 1;
int CurrentMidiChannel = 0;

void loop() {

  // Play notes in banks 0, 1, 2 and 3
  // (all on channel 0)
  //
  for ( int bank = 0; bank < 4; bank ++ )
  {
    CurrentMidiBank = bank;
    midiBank( CurrentMidiChannel, CurrentMidiBank );

    // play notes from G-3 (0x43) to G-4 (0x4F):
    // for (int note = 0x1E; note < 0x5A; note ++)
    for (int note = 0x43; note < 0x4F; note ++)
    {
      noteOn( CurrentMidiChannel, note, 0x45);
      delay(1000);

      noteOff( CurrentMidiChannel, note, 0x00);
      delay(1000);
    }

    delay( 1500 );
  }
}

// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:

void midirelease ( byte channel, byte release)
{
  midiMsg( (0xB0 | channel ), 0x48, release);

  Serial.write(release );
}

void midiattack ( byte channel, byte attack)
{
  midiMsg( (0xB0 | channel ), 0x49, attack);

  Serial.write( attack);
}
void midiBank( byte channel, byte bank )
{
  // Program Change, Bank select LSB = bank
  midiMsg( (0xB0 | channel ), 0x20, bank );

  // Program Change, program 0
  Serial.write( (0xC0 | channel) );
  Serial.write( bank );

}

// Send a MIDI note-on message.
void noteOn(byte channel, byte note, byte volume)
{
  midiMsg( (0x90 | channel), note, volume);
}

// Send a MIDI note-off message.
void noteOff(byte channel, byte note, byte volume)
{
  midiMsg( (0x80 | channel), note, volume );
}

// Send a general MIDI message
//
void midiMsg(byte cmd, byte data1, byte data2 )
{
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}




MarkT

Your sketch never calls midirelease() or midiattack()!
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Grumpy_Mike

Your sketch never calls midirelease() or midiattack()!
Call them in the setup function if you are not going to change them.

Remove the lines
Code: [Select]
Serial.write(release );
and
Serial.write( attack);

142victoria

I have removed  the lines , Serial.write(release ); and Serial.write( attack); as sugested from the sketch.

I have tried to call midirelease() / midiattack()! and also tried every thing else I can think of.

I cannot get this to work. I do not know what I am doing.

I attach a copy of my attempt below.

Code: [Select]
#include
void setup() {
  // Set MIDI baud rate:
  Serial.begin(31250);

}
byte midirelease();
byte midiattack();
int CurrentMidiBank = 1;
int CurrentMidiChannel = 0;
int release = 18;  // =500ms
int attack = 18;   // =500ms


void loop() {

  // Play notes in banks 0, 1, 2 and 3
  // (all on channel 0)
  //
  for ( int bank = 0; bank < 4; bank ++ )
  {
    CurrentMidiBank = bank;
    midiBank( CurrentMidiChannel, CurrentMidiBank );

    // play notes from G-3 (0x43) to G-4 (0x4F):
    // for (int note = 0x1E; note < 0x5A; note ++)
    for (int note = 0x43; note < 0x4F; note ++)
    {
      noteOn( CurrentMidiChannel, note, 0x45);
      delay(1000);

      noteOff( CurrentMidiChannel, note, 0x00);
      delay(1000);
    }

    delay( 1500 );
  }
}

// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:

void midirelease ( byte channel, byte release)
{
  midiMsg( (0xB0 | channel ), 0x48, release);

}

void midiattack ( byte channel, byte attack)
{
  midiMsg( (0xB0 | channel ), 0x49, attack);
}
void midiBank( byte channel, byte bank )
{
  // Program Change, Bank select LSB = bank
  midiMsg( (0xB0 | channel ), 0x20, bank );

  // Program Change, program 0
  Serial.write( (0xC0 | channel) );
  Serial.write( bank );

}

// Send a MIDI note-on message.
void noteOn(byte channel, byte note, byte volume)
{
  midiMsg( (0x90 | channel), note, volume);
}

// Send a MIDI note-off message.
void noteOff(byte channel, byte note, byte volume)
{
  midiMsg( (0x80 | channel), note, volume );
}

// Send a general MIDI message
//
void midiMsg(byte cmd, byte data1, byte data2 )
{
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

Grumpy_Mike

Where in that code do you try and call the midirelease() & midiattack() functions?

I note you have defined a byte variable with the same name
Code: [Select]

byte midirelease();
byte midiattack();

Why are you doing that? It is not calling those functions.

Remove them and make your setup function:-

Code: [Select]
void setup() {
  // Set MIDI baud rate:
  Serial.begin(31250);
  midirelease(0,18);
   midiattack(0,18);
}


Also why do you have just #include at the start of your sketch?

142victoria

Grumpy_Mike
Ok I have altered the code as  you suggested .
This is still not working.
I have just #include at the start of your sketch because in cutting and pasting sketch I missed out <MIDI.h> .
I learn from my mistakes and I am still making them.
Altered code attached 







Code: [Select]
#include  <MIDI.h>
void setup() {
  // Set MIDI baud rate:
  Serial.begin(31250);
  midirelease(0, 18);
  midiattack(0, 18);
}

int CurrentMidiBank = 1;
int CurrentMidiChannel = 0;
int release = 18;  // =500ms
int attack = 18;   // =500ms


void loop() {

  // Play notes in banks 0, 1, 2 and 3
  // (all on channel 0)
  //
  for ( int bank = 0; bank < 4; bank ++ )
  {
    CurrentMidiBank = bank;
    midiBank( CurrentMidiChannel, CurrentMidiBank );

    // play notes from G-3 (0x43) to G-4 (0x4F):
    // for (int note = 0x1E; note < 0x5A; note ++)
    for (int note = 0x43; note < 0x4F; note ++)
    {
      noteOn( CurrentMidiChannel, note, 0x45);
      delay(1000);

      noteOff( CurrentMidiChannel, note, 0x00);
      delay(1000);
    }

    delay( 1500 );
  }
}

// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:

void midirelease ( byte channel, byte release)
{
  midiMsg( (0xB0 | channel ), 0x48, release);

}

void midiattack ( byte channel, byte attack)
{
  midiMsg( (0xB0 | channel ), 0x49, attack);
}
void midiBank( byte channel, byte bank )
{
  // Program Change, Bank select LSB = bank
  midiMsg( (0xB0 | channel ), 0x20, bank );

  // Program Change, program 0
  Serial.write( (0xC0 | channel) );
  Serial.write( bank );

}

// Send a MIDI note-on message.
void noteOn(byte channel, byte note, byte volume)
{
  midiMsg( (0x90 | channel), note, volume);
}

// Send a MIDI note-off message.
void noteOff(byte channel, byte note, byte volume)
{
  midiMsg( (0x80 | channel), note, volume );
}

// Send a general MIDI message
//
void midiMsg(byte cmd, byte data1, byte data2 )
{
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

MarkT

You need to issue the commands for the channel in question - so if you change CurrentMidiChannel to
something other than zero, your attack/release commands will need changing too.

You might want to select the bank before sending control change messages, they are likely to be
bank-specific, but read the docs for the MIDI device in question if possible.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Grumpy_Mike

You need to issue the commands for the channel in question - so if you change CurrentMidiChannel to
something other than zero, your attack/release commands will need changing too.
But the function says:-
Code: [Select]
void midirelease ( byte channel, byte release)
{
  midiMsg( (0xB0 | channel ), 0x48, release);
}

So the channel is passed as a parameter to the function.

142victoria

I am getting confused, I do not understand the last two posts and there relevance as to getting my sketch working.

Grumpy_Mike

Quote
I do not understand the last two posts and there relevance as to getting my sketch working.
The relevance is that your code is rubbish, it seem that you don't even know how to call a function. This is one of the very basic fundamentals you need to do when you write a program.

As it stands your code is not sending the control data to your MIDI device. Which is why you are not hearing any effect. We are attempting to show you what corrections you need to make to your code in order for it to send this data.

Each MIDI channel you use requires this data to be sent to it, MarkT was pointing this out in reply #10. Then I was pointing out to Mark that the function you had written contains the channel data as one of the parameter to pass to it. So as long as you call this function for each channel you want to use along with the correct channel then all will be well.

142victoria

Last post understood.
Ok, as you say my sketch is rubbish and my programming skills are also rubbish, this I know and this is why I am seeking advice.
I attach a modified sketch which does not work and is also properly rubbish, but is best I can think off.   
What do I need to do?
Code: [Select]
#include

int bank = 1;
int channel = 0;
int release = 18;
int attack = 18;




void setup() {
  // Set MIDI baud rate:
  Serial.begin(31250);
  midirelease(0, 18);    // =500ms
  midiattack(0, 18);
}


void loop()
{

  midiattack(channel, attack);
  midirelease( channel, release );

  // Play notes in banks 0, 1, 2 and 3
  // (all on channel 0)
  //
  for ( int bank = 0; bank < 4; bank ++ )
  {
    midiBank( channel, bank );

    // play notes from G-3 (0x43) to G-4 (0x4F):
    for (int note = 0x43; note < 0x4F; note ++)
    {

      noteOn( channel, note, 0x45, attack);

      delay(1000);

      noteOff( channel, note, 0x00, release);

      delay(1000);
    }

    delay( 1500 );
  }
}

// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:

void midirelease ( byte channel, byte release)
{
  midiMsg( (0xB0 | channel ), 0x48, release);
  Serial.write( (0xC0 | channel) );
  Serial.write( release );
}

void midiattack ( byte channel, byte attack)
{
  midiMsg( (0xB0 | channel ), 0x49, attack);
  Serial.write( (0xC0 | channel) );
  Serial.write( attack );
}

void midiBank( byte channel, byte bank )
{
  // Program Change, Bank select LSB = bank
  midiMsg( (0xB0 | channel ), 0x20, bank );

  // Program Change, program 0
  Serial.write( (0xC0 | channel) );
  Serial.write( bank );

}

// Send a MIDI note-on message.
void noteOn(byte channel, byte note, byte velocity, byte attack)
{
  midiMsg( (0x90 | channel), note, velocity );
}

// Send a MIDI note-off message.
void noteOff(byte channel, byte note, byte velocity, byte release)
{
  midiMsg( (0x90 | channel), note, velocity );
}

// Send a general MIDI message
//
void midiMsg(byte cmd, byte data1, byte data2 )
{
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}





Go Up