Loading...
  Show Posts
Pages: 1 ... 21 22 [23] 24 25 ... 48
331  Using Arduino / Audio / Re: Class for playing MIDI files from the Arduino - testers needed on: December 30, 2012, 05:17:45 pm
Updated version of the library is attached. This implements points discussed above plus some additional tidy up of the debug messages.
332  Using Arduino / Audio / Re: Class for playing MIDI files from the Arduino - testers needed on: December 30, 2012, 04:27:52 pm
I take your point, but they are actually not allowed to exist in the stream according to the Standard MIDI File documentation. If they are in there then either the file should be considered invalid (ie, abandon it) or the sync has to be to the next byte with a top bit not set, which should be the next deltaT.

The problem with MIDI files is that they are sequential - each note or event is defined in a time offset (deltaT) from the previous one and if you sync forward you get out of time sequence with respect to the other tracks. I actually had this happening early in the piece and it sounds awful.

I'll need to think about this one.

Edit - on reflection, the most straightforward way is to make the track invalid (ie, mark it as end of track) and stop playing it. This allows the other tracks to play on and the file is not totally lost.
333  Using Arduino / Audio / Re: Class for playing MIDI files from the Arduino - testers needed on: December 30, 2012, 02:50:15 pm
Thanks robtillart for taking the time to look and comment.

Quote
starnges that an destructor calls initialize
Initially I had some memory allocation going on and I had to free memory (that was being done in close()), so the destructor needed to call close(). I have renamed initialise() to resetTrack() which may give us all less of an uncomfortable feeling.

Quote
saw you have a dump mode (but it is a cooked dump not a raw dump)
There is a sketch that does a raw dump of the data in the chunks after the header, without using the library. I also use a utility called "MIDI File Analyzer" (picked up somewhere off a Google link) that basically agrees with my own dump(s) of the files, so I am have a high confidence the dumps are correct.

Quote
not handling all values between 0xf1 ... 0xff:
Yes, correct. These values are real time valuies that appear in a MIDI live stream as control messages but are not valid in a file - 0xf1 is undefined, 0xf2 is Start a sequence, 0xf3 is Continue sequence. 0xf4 is Stop sequence, 0xf5 is undefined, 0xf6 is Active Sense (like a watchdog timer), 0xff is Reset System. All others in this range should be processed.

Quote
x not used
A leftover from when I had an intermediate result being calculated.

Quote
syntactically wrong as you should use the boolean && not the bitwise &
and it can be faster
Agree. Suggested version also saves 1 byte of stack space :-)

Quote
many loops use int i;   you could check if uint8_t is enough ?
Good point, will check.

Quote
So many #if 's makes me wonder if you could not better
Great point here. I have done what you suggested before and I don't know why I didn't do it here as well. This will also make the code more maintanable, as an alternative output stream is easier to implement if needed.

I'll post an updated version of the library once implemented and tested.
334  Using Arduino / Programming Questions / Re: I'm not exactly sure how to put this...I'm new to this on: December 30, 2012, 01:38:58 am
What strings?

You are in a for loop in your code. You are already doing what you need to do but in the wrong sequence, which is what you say you see. Look at the code and read the other messages ...

Edit: lloyddean has given the solution.
335  Using Arduino / Programming Questions / Re: I'm not exactly sure how to put this...I'm new to this on: December 30, 2012, 01:26:37 am
If you are playing music you can't add in additional delays, so the suggestion is that you turn the led on just before you play the tone, then turn it off straight after you have paused between notes. This automatically synchronizes as the led can only be on while the sound is on.
336  Using Arduino / Programming Questions / Re: I'm not exactly sure how to put this...I'm new to this on: December 30, 2012, 01:04:19 am
I would set the led high, play the note including the note delay, then turn the led off.

Btw, you are using the numeral 8 instead of speaker in the tone function call.
337  Using Arduino / Audio / Library for playing MIDI files from the Arduino on: December 29, 2012, 09:17:12 pm
Update - See last posting.
 
I have been working on a class to read MIDI files (Standard MIDI Format) from an SD card and play them through a MIDI serial interface on the Arduino. My aim is to be able to play any MIDI file as long as it is properly constructed.

This code is now very stable but at a point where (a) I have been looking at it too long, and (b) I need input from people who know more about MIDI than I do.

The class generally works ok, but there are a few files that do not play well (or at all) and I am stumped as to what makes these files 'special'. All the MIDI files are playable on my Windows PC and I can't see why is in the data that makes them not play when I print out what is in the file (using the dump() method in the class).

All the library code, some example program files that call the library, and a collection of MIDI files are attached. There is a dependency on other libraries - MIDI, SdFat and Flash. Locations to get these is documented in MIDIFile.h. You should also have a working MIDI serial interface - OUT is the only channel used form the Arduino for this software.

The problems I am experiencing are probably best explained in the MIDIFile_Play example - some of the files play really well and other sound strange or don't even start. My feeling is that I am not getting some of the time signals correct as the Time Signature META event is only partially processed, but I can't see how what I have ignore affects anything (ignorance here, probabaly, as I am not a musician).

Happy to get feedback and or help on sorting these issues out from anyone with some free time and interest to test or review the code.

Thanks in advance.
338  Using Arduino / Programming Questions / Re: what is Map instruction do ??? on: December 29, 2012, 04:06:24 am
map() takes an input range and maps it to an output range (ie, it scales).

So if the input value was 2 and the range was between 0 and 10, then mapping it to the new range 0 to 100 will return the value 20. Note that if you had 11 in the first instance it would return 110, so you often need to use constrain() if you do not want these values outside the full range.
339  Using Arduino / Programming Questions / Re: For loop not working... on: December 25, 2012, 03:05:43 pm
Quote
for(int i=0;i = steps;i++){
should be
for(int i=0;i < steps;i++){

if you have declared steps[15] as an array
340  Using Arduino / Programming Questions / Re: call of overloaded with average lib ! on: December 24, 2012, 02:42:38 pm
Quote
Interrupt:87: error: call of overloaded 'mean(volatile int [20], int)' is ambiguous
/Users/florent/Documents/Arduino/libraries/Average/Average.h:39: note: candidates are: int mean(int*, int) <near match>
/Users/florent/Documents/Arduino/libraries/Average/Average.h:40: note:                 unsigned int mean(unsigned int*, int) <near match>


Looks like you are trying to pass an array to the function. Don't put the array subscript in the mean function call ("'mean(volatile int [20], int)'"). The name of the array is all you need as that is a pointer to the data. I am guessing the second parameter is the size of the array, and that is an integer.
341  Using Arduino / Programming Questions / Re: Library referencing other libraries will not compile - SOLVED on: December 21, 2012, 03:33:49 pm
Just goes to show you can stare at code and not see the obvious things.

Thanks Paul, that was the problem. Once I made all the text case consistent that problem went away and now I have to deal with other issues...
342  Using Arduino / Programming Questions / Re: Quick question about populating arrays on: December 21, 2012, 04:55:53 am
You can. You need to enclose all the elements for a structure within curly braces and separate these groups by comms.. Essentially each array element is a group of variables instead of the individual items if a simple array.

Code:
struct_type data[3] = {{1,2,3},{3,4,5},{6,7,8}};
343  Using Arduino / Programming Questions / Re: Can you interrupt an interrupt? on: December 21, 2012, 02:52:40 am
You can interrupt an interrupt. That's why the advice is to keep them short and fast so that you don't miss any other interrupts.
344  Using Arduino / Programming Questions / Library referencing other libraries will not compile - SOLVED on: December 21, 2012, 02:04:42 am
I am creating a library (called MIDIFile) that implements a class that can be used to read a MIDI file from an SD card and stream it to a MIDI device. I am using the SDFat library to read the SD card, so this is referenced in the library.

When I try and compile a test program, I get definition errors for items that are defined in the SDFat library. It just seems like the compiler cannot find the header file and no matter what combinations I try (order of includes, bracket types, relative paths) they don't seem to make any difference.

MIDI_FileRead2.ino:1:19: warning: SDFat.h: No such file or directory

SDFile and my new library are in the Sketchbook/libraries folder. I am running windows and I have the IDE 1.0.3.

Clearly I am not adding stuff in the header files in the right order, so here are the start of the files with the include sequence, and the erroe message I get. I am sure someone will have solved this before...

Midifile.h - the library header file
Code:
#ifndef _MIDIFILE_H
#define _MIDIFILE_H

// Arduino MIDI File library
//
// A class which can read Standard MIDI files.
//

#include <Arduino.h>
#include <SdFat.h>

class MidiFile
{
  public:
    MidiFile(void);
    MidiFile(uint8_t ss);
    MidiFile(const char* aFile);
    MidiFile(uint8_t ss, const char* aFile);

    ~MidiFile(void);


MidiFile.cpp - library code file implementing the class
Code:
// Arduino MIDI File library
//
// A class which can read Standard MIDI files.
//

#include <string.h>
#include "MidiFile.h"


My test program
Code:
#include <SDFat.h>
#include <MidiFile.h>

/*
 * SD chip select pin.  Common values are:
 * Arduino Ethernet shield, pin 4.
 */
#define  SD_SELECT  4
#define  MIDI_FILE  "LOOPDEMO.MID"

MidiFile SMF(SD_SELECT, MIDI_FILE);

/*
void dumpBuffer(SdFile *f, int len)
{
  for (int i=0; i<len; i++)
  {
    uint8_t  c = f->read();
    
    if ((i!=0) && ((i%8) == 0)) Serial.println();
    Serial.print(' ');
    if (c<=0xf) Serial.print('0');
    Serial.print(c, HEX);
  }
}
*/
void DumpSMF(void)
{
  Serial.println(SMF.getFilename());
  Serial.print("File Version:\t");
  Serial.println(SMF.getFormat());
  Serial.print("Tracks:\t\t");
  Serial.println(SMF.getTrackCount());
  Serial.print("Speed:\t\t");
  Serial.println(SMF.getTicksPerQuarterNote());
}

void setup(void)
{
  Serial.begin(57600);
  Serial.println("[MIDI file reader]");
  
  SMF.load();
  DumpSMF();
 
  // close the file:
  SMF.close();
}

void loop(void)
{
}

Error messages (compiler verbose turned on):
Code:
F:\arduino\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=103 -IF:\arduino\hardware\arduino\cores\arduino -IF:\arduino\hardware\arduino\variants\standard -IF:\Marco\Documents\Programming\Arduino\Sketchbook\libraries\MIDIFile C:\Users\Marco\AppData\Local\Temp\build6922185689476771770.tmp\MIDI_FileRead2.cpp -o C:\Users\Marco\AppData\Local\Temp\build6922185689476771770.tmp\MIDI_FileRead2.cpp.o
MIDI_FileRead2.ino:1:19: warning: SDFat.h: No such file or directory
In file included from MIDI_FileRead2.ino:2:
F:\Marco\Documents\Programming\Arduino\Sketchbook\libraries\MIDIFile/MidiFile.h:33:19: warning: SdFat.h: No such file or directory
In file included from MIDI_FileRead2.ino:2:
F:\Marco\Documents\Programming\Arduino\Sketchbook\libraries\MIDIFile/MidiFile.h:132: error: 'SdFat' does not name a type
F:\Marco\Documents\Programming\Arduino\Sketchbook\libraries\MIDIFile/MidiFile.h:133: error: 'SdFile' does not name a type
F:\Marco\Documents\Programming\Arduino\Sketchbook\libraries\MIDIFile/MidiFile.h:136: error: 'SdFile' has not been declared
F:\Marco\Documents\Programming\Arduino\Sketchbook\libraries\MIDIFile/MidiFile.h:137: error: 'SdFile' has not been declared
345  Using Arduino / Programming Questions / Re: Replace Buttons with LDR's on: December 20, 2012, 03:17:38 pm
Can't test this as I have not got your libraries, but this the changes are implemented:

Code:
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"


SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the filesystem on the card
FatReader f;      // This holds the information for the file we're play

WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

#define DEBOUNCE 5  // button debouncer

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
/// --- byte buttons[] = {14, 15, 16, 17, 18, 19};
byte buttons[] = {A0, A1, A2, A3, A4, A5};

// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)/sizeof(buttons[0])
#define ON_THRESHOLD 512  // change to suit values retruned from LDR. Values greater will be ON

// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
 extern int  __bss_end;
 extern int  *__brkval;
 int free_memory;
 if((int)__brkval == 0) {
   free_memory = ((int)&free_memory) - ((int)&__bss_end);
 }
 else {
   free_memory = ((int)&free_memory) - ((int)__brkval);
 }
 return free_memory;
}

void sdErrorCheck(void)
{
 if (!card.errorCode()) return;
 putstring("\n\rSD I/O error: ");
 Serial.print(card.errorCode(), HEX);
 putstring(", ");
 Serial.println(card.errorData(), HEX);
 while(1);
}

void setup() {
 byte i;

 // set up serial port
 Serial.begin(9600);
 putstring_nl("WaveHC with ");
 Serial.print(NUMBUTTONS, DEC);
 putstring_nl("buttons");

 putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
 Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!

 // Set the output pins for the DAC control. This pins are defined in the library
 pinMode(2, OUTPUT);
 pinMode(3, OUTPUT);
 pinMode(4, OUTPUT);
 pinMode(5, OUTPUT);

 // pin13 LED
 pinMode(13, OUTPUT);

 // Make input & enable pull-up resistors on switch pins
 for (i=0; i< NUMBUTTONS; i++) {
   pinMode(buttons, INPUT);
   digitalWrite(buttons, HIGH);
 }

 //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
 if (!card.init()) {         //play with 8 MHz spi (default faster!)
   putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
   sdErrorCheck();
   while(1);                            // then 'halt' - do nothing!
 }

 // enable optimize read - some cards may timeout. Disable if you're having problems
 card.partialBlockRead(true);

// Now we will look for a FAT partition!
 uint8_t part;
 for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
   if (vol.init(card, part))
     break;                             // we found one, lets bail
 }
 if (part == 5) {                       // if we ended up not finding one  smiley-sad
   putstring_nl("No valid FAT partition!");
   sdErrorCheck();      // Something went wrong, lets print out why
   while(1);                            // then 'halt' - do nothing!
 }

 // Lets tell the user about what we found
 putstring("Using partition ");
 Serial.print(part, DEC);
 putstring(", type is FAT");
 Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?

 // Try to open the root directory
 if (!root.openRoot(vol)) {
   putstring_nl("Can't open root dir!"); // Something went wrong,
   while(1);                             // then 'halt' - do nothing!
 }

 // Whew! We got past the tough parts.
 putstring_nl("Ready!");

 TCCR2A = 0;
 TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

 //Timer2 Overflow Interrupt Enable
 TIMSK2 |= 1<<TOIE2;


}

SIGNAL(TIMER2_OVF_vect) {
 check_switches();
}

void check_switches()
{
 static byte previousstate[NUMBUTTONS];
 static byte currentstate[NUMBUTTONS];
 byte index;

 for (index = 0; index < NUMBUTTONS; index++) {
   currentstate[index] = analogRead(buttons[index]) >= ON_THRESHOLD;   // read the LDR 'button'

   /*     
   Serial.print(index, DEC);
   Serial.print(": cstate=");
   Serial.print(currentstate[index], DEC);
   Serial.print(", pstate=");
   Serial.print(previousstate[index], DEC);
   Serial.print(", press=");
   */

   if (currentstate[index] == previousstate[index]) {
     if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
         // just pressed
         justpressed[index] = 1;
     }
     else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
         // just released
         justreleased[index] = 1;
     }
     pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
   }
   //Serial.println(pressed[index], DEC);
   previousstate[index] = currentstate[index];   // keep a running tally of the buttons
 }
}


void loop() {
 byte i;
 static byte playing = -1;

 if (pressed[0]) {
   if (playing != 0) {
     playing = 0;
     playfile("DO.WAV");
   }
 }
 else if (pressed[1]) {
   if (playing != 1) {
     playing = 1;
     playfile("RE.WAV");
   }
 }
 else if (pressed[2]) {
   if (playing != 2) {
     playing = 2;
     playfile("MI.WAV");
   }
 }
 else if (pressed[3]) {
   if (playing != 3) {
     playing = 3;
     playfile("FA.WAV");
   }
 }
 else if (pressed[4]) {
   if (playing != 4) {
     playing = 4;
     playfile("SO.WAV");
   }
 }
 else if (pressed[5]) {
   if (playing != 5) {
     playing = 5;
     playfile("LA.WAV");
   }
 }

 if (! wave.isplaying) {
   playing = -1;
 }
}



// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
 // call our helper to find and play this name
 playfile(name);
 while (wave.isplaying) {
 // do nothing while its playing
 }
 // now its done playing
}

void playfile(char *name) {
 // see if the wave object is currently doing something
 if (wave.isplaying) {// already playing something, so stop it!
   wave.stop(); // stop it
 }
 // look in the root directory and open the file
 if (!f.open(root, name)) {
   putstring("Couldn't open file "); Serial.print(name); return;
 }
 // OK read the file and turn it into a wave object
 if (!wave.create(f)) {
   putstring_nl("Not a valid WAV"); return;
 }

 // ok time to play! start playback
 wave.play();
}

Pages: 1 ... 21 22 [23] 24 25 ... 48