Audio Library

Status
Not open for further replies.
@ Paul
sorry for confusing. my english is bad and it is sometimes hard to articulate.
i don't use usb midi. and the midi problem is gone. i missed the custom teensy midi library but i solved it with the standard midi lib from arduino like i mentioned before.
for the simultaneously sound problem:
i use raw files. separate objects and i have a mixer object. i trigger the sound objects via midi. sometimes (often but not always) if i play two or more sounds at the same time, i have a strange glitch and it is hearable in the lower range (bass drum i.e.)
here is my sketch:

#include <MIDI.h>
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>

HardwareSerial Uart = HardwareSerial();
MIDI_CREATE_INSTANCE(HardwareSerial, Uart, midi2);

AudioPlaySdRaw track1, track2, track3, track4;
AudioMixer4 mixer1;
AudioOutputI2S dac;

AudioConnection c0(track1, 0, mixer1, 0);
AudioConnection c1(track2, 0, mixer1, 1);
AudioConnection c2(track3, 0, mixer1, 2);
AudioConnection c3(track4, 0, mixer1, 3);
AudioConnection c4(mixer1, 0, dac, 0);
AudioConnection c5(mixer1, 0, dac, 1);

AudioControlSGTL5000 audioShield;


const char* track_1_sound = "BD1.RAW";
const char* track_2_sound = "HH1.RAW";
const char* track_3_sound = "SD1.RAW";

int active_track = 1;

void HandleNoteOn(byte channel, byte pitch, byte velocity){
switch(pitch){
case 64:
track1.play(track_1_sound);
break;
case 65:
track2.play(track_2_sound);
break;
case 66:
track3.play(track_3_sound);
break;
}
}
void HandleNoteOff(byte channel, byte pitch, byte velocity){

}

void HandleProgramChange (byte channel, byte number, byte value){

}

void setup() {

midi2.setHandleNoteOn(HandleNoteOn); // Put only the name of the function
midi2.setHandleNoteOff(HandleNoteOff);
midi2.setHandleProgramChange(HandleProgramChange);
midi2.begin(MIDI_CHANNEL_OMNI);
delay(100);
AudioMemory(50);
audioShield.enable();
audioShield.volume(0.6);
SPI.setMOSI(7);
SPI.setSCK(14);
SD.begin(10);

}
void loop () {

midi2.read();

}
 
hello again. after investigating my problem i found that PlayFromSketch example doesn't have problems with multiple sounds at once at all. could it be just the sd card speed?
 
ok. so i bought a new microsd card (sandisc sdhc ultra (10) 8gb) . little bit better now from performance side but i still notice clicking and poping when multiple sounds are playing. especialy when a sound plays and a another starts- there are problems. again : i'm using only short drum raw files. and again every sound is a "object" (polyphone). can this be improved?
regards,
van
 
Why don't you put your drum samples directly in the flash of the Teensy?
How much sample memory do you need?
 
Why don't you put your drum samples directly in the flash of the Teensy?
How much sample memory do you need?
at the moment there are about 2MB of samples on the sd card. but let's say at one song i'll use about 400KB.
1. can i load dynamically in the flash while the program is running?
2. how- can you please give me an example?
regards!
van
p.s. i was hoping to use the sd card in real time...
 
I'm pretty sure the sd card should work without
clicking. Did tou try reformatting your card ? Helped solve some problems over here.
 
I'm pretty sure the sd card should work without
clicking. Did tou try reformatting your card ? Helped solve some problems over here.

yes, i tryed but no succes...
the problem looks like this (if it makes sence):

sound1..|-----------------^(pop)------------>
sound2........................|------------------->
 
It sounds like the (currently unsupported) optional low-latency flash chip on the audio board would be ideal for that sort of thing.
An optional W25Q128FV flash memory chip on the bottom side is also accessed using SPI, with the MEMCS pin to select the chip. Future versions of the audio library may use this low latency flash memory for short audio clips or wavetable synthesis. Currently there is no software support for this chip.

W25Q128FV is 128Mbit (16Mbytes).

Also, the distinction between MLC or TLC Flash (used in consumer SD cards) and SLC Flash (used in Industrial SD cards) may be relevant here.
http://panasonic.net/avc/sdcard/industrial_sd/lineup.html
http://uk.mouser.com/new/panasonic/panasonic-industrial-sd-cards/
However, those cards are pretty pricey, so the low latency flash chip may be a better solution.
http://www.digikey.com/product-detail/en/W25Q128FVSIG/W25Q128FVSIG-ND/3008697
 
If I understand correctly, somewhere in the SD library, there's a blocking operation that's long enough to disrupt the flow of data to the sound chip? I assume we've ruled out the possibility that the code to start a sample configures something that temporarily disrupts any currently playing sound?

How about a workaround? Right before sound2 starts playing, drop the volume to zero. Start the sound. Restore the volume to the previous level.

This might be less noticeable than a pop. If the volume change happens quickly enough, it might not be noticeable at all.

Alternative workaround: To play multiple sounds, mix the sounds in a RAM buffer before playing them so the audio chip only sees a single sound. If this workaround still pops, seems like the bug would have to be in the mixing code.
 
@pictographer

thank you very much for the constructive suggestion!
workaround1: don't work good. it's just a liitle bit better but still very noticable click.
wrokaround2: could you give me an example how to do this, please?

i just saw that paul mentioned something about an SPI problem. perhaps the problem is in there...
 
Last edited:
Paul what the hell were you thinking? :)

Code:
void loop() {
  
  if(fps>24) { // for best effect make your terminal/monitor a minimum of 62 chars wide and as high as you can.
    Serial.println();
    fps=0;
    uint8_t leftPeak=peak_L.Dpp()/2184.5321; // 65536 / 2184.5321 ~ 30.
    for(cnt=0;cnt<30-leftPeak;cnt++) Serial.print(" ");
    while(cnt++<30) Serial.print("<");
    Serial.print("||");
    uint8_t rightPeak=peak_R.Dpp()/2184.5321;
    for(cnt=0;cnt<rightPeak;cnt++) Serial.print(">");
    while(cnt++<30) Serial.print(" ");
    peak_L.begin(); // no need to call .stop if all you want
    peak_R.begin(); // is to zero it.
  }
}

I'm referring to this:
// 65536 / 2184.5321 ~ 30.

Why would you not just use 32?

Or did someone else write this example? If so then my question is directed at them!

I thought this was some weird constant I was going to have to remember for a moment.
 
I wrote that crap.

I was thinking that trying to emulate an effective simile of LEDs coming from a central point in a display of amplitude perhaps 30 LEDs per side would look OK so by using those decisions and deciding to have a separator etc etc it came out like it did.\

Perhaps for you 32 is the logical amount of elements per side in a display but when I was a kid the first LED amplitude display I saw had 5 LEDs per side, next I saw 10s and then I saw 12s - haven't counted anybody else's since and I can't see why anybody who wants to have any number of them of their choosing can't.

You can set up to have as much granularity per side as you want; you can even do your absolute best to absolutely stream line all things, and even make absolutely certain that no floating point math is employed so that your creation is stunningly brilliant and so efficient and streamlined that the processor will have even more IDLE time in between calling the other crap I wrote, the AudioPeak object, which needs a reasonable amount of time (between calls) to make meaningful results.


It's at least almost obvious that you understand what that calculation controls and you understand how to fix it to your liking so I am going to ask you: What the hell were you thinking sounding so rude about it when it is actually fairly obviously what it is and you can make it anything else you'd like it to be?

I can't wait to see your contrib, wonder if I'll be able to hold myself back from critiquing the hell out of it.
 
Dude, no need to take offense over a minor critique of a single line of code that amounts to a division. I just thought it was a really odd choice to divide by a floating point number to get 30 elements when 32 seemed like the more logical and simple way to go.

If you did it because bar displays typically have 10 elements, then I can see the logic behind that. That's all I wanted to know - why the decision was made to do it that way.

And you are free to critique my stuff all you like. That is how we get better at what we do.


so I am going to ask you: What the hell were you thinking sounding so rude about it when it is actually fairly obviously what it is and you can make it anything else you'd like it to be?

I was thinking that Paul's an extremely skilled programmer, and he must have had a really good reason for doing this that I can't see.

PS:
Note the smiley face on my original post.
 
Last edited:
I like that you've named the audio input and output objects audioInput and audioOutput. I think it makes it easier to understand that the user can change the object type, and what the connection object initialization is actually doing than naming them after the object type.
 
Last edited:
I'm lost.

Where the heck is audiostream.h? It's referenced by several files but it doesn't seem to be in the library directory, or on the github page.

Where are the audioconnections and audiomemory functions? I'm trying to figure out how to calculate how much memory to allocate instead of just plugging a random number in and hoping it works, but Windows 7 search refuses to search for text inside of source code files despite all my efforts so I'm just clicking random files looking for it, but so far I've had no luck.
 
Actually I just found Audiostream. I thought I remembered it being part of the Teensy code and checked the hardware directory and it's in there. I guess it makes sense for it to be there if it has Teensy specific code (I assume it does stuff with DMA?), but at the same time, it seems like a bad idea to have the source code for a library spread out in multiple places like that. I'd have never found it if I hadn't asked about it months ago.

/edit

nlecaude: Thanks, I found it right after I posted. :)

Oh, and I get that this is probably just how it has to be done on the Arduino. I just wish it were simpler.
 
Last edited:
I've found a bug in the audio library.

I wanted to trigger a wav file when a particular input was received, and that bit works, but the code wasn't waiting for the wav file to finish playing before checking to see if it should trigger again.

The problem seems to be that wav.isplaying() checks to see if the current state is < 8. But when you call the function to play the wav, it sets the state to 8. This is the state during which it reads the file header.

Now, perhaps this behavior was intentional, as the audio may not actually ever play if the header is corrupt. But it does severely limit the usefulness of isplaying() if it is not true from the moment you call the function to play the wave file. I know I would prefer it if it reported that it was not playing if the file didn't exist. And if it cannot start because header is corrupt, then it also seems like correct behavior for it to report it is not playing. But it seems like both of those should be determined at the time the function to play the wave is called. If that cannot happen, then perhaps there needs to be a function to report that is it being prepared for playback or something as well.
 
Oh, and I just checked, and the state info is private, so I can't just access that directly without modifying the library.
 
This works well enough for this project:

Code:
      if (wav.play("vigo002.wav")) { // Attempt to play file.  
        // File was found, and we're reading the file header.
        while (!wav.isPlaying()) {} // Wait for the header to be read and playback to begin.

But it's not a great solution since I have to delay entering the next state until the file begins to play.
 
I've had troubles with this too when trying to loop files, need to add delays which is not very elegant.
 
I'm lost.

Where the heck is audiostream.h? It's referenced by several files but it doesn't seem to be in the library directory, or on the github page.

Where are the audioconnections and audiomemory functions? I'm trying to figure out how to calculate how much memory to allocate instead of just plugging a random number in and hoping it works, but Windows 7 search refuses to search for text inside of source code files despite all my efforts so I'm just clicking random files looking for it, but so far I've had no luck.

In my interaction with Windows 7 I haven't been able to find the 'search for files named * where text inside matches $' feature either but if you navigate its file explorer to the root directory of your arduino+teensyduino install and then enter 'audiostre' into the search box to the right of the address bar it should at least find things by filename - you say you found it but you don't say that it was easily found after all so I've posted this info.


Ps. I saw the smiley face and took it as making cheekier the ungrateful rudeness I perceive 'what the hell were you thinking?' to be in the context and setting in which you used it. Oddly enough, had you identified and singled me out for it I would have been much less offended because reasons to be grateful to me about anything to do with the Audio Library or Teensy in general are very very few indeed but when I saw that directed at Paul (to whom we all owe a lot of gratitude about this stuff) it really seemed pretty ugly, and certainly an unnecessary way to challenge him, to me.
 
I'm having an issue with random playback of wave files. The board seems to crash occasionally, even though the last file it displays on the serial monitor is in range. And it's never on the same file.

Code:
    AudioNoInterrupts(); 
      
      root = SD.open("/");
      root.rewindDirectory(); // Go back to the first file in the directory.
      
      int index = random(fileCount) + 1; // Choose a random wav file to play. [1..filecount]
      int count = 0;
      
      while (count < index) {  
        
        entry = root.openNextFile();
        Serial.println(entry.name());
        
        if (!entry) { Serial.println("Error when choosing wav file!"); break; } // If no more files, exit loop. This should be impossible!
        
        if (entry.isDirectory()) { continue; } // If this is a directory, it doesn't count.
        // TODO: If this is not a wav file, it doesn't count.
        
        count++;
        
      }
      
      AudioInterrupts(); 
              
      if (wav.play(entry.name())) { // Attempt to play file. Using above method it should be impossible to get here without picking a file, but it's still possible the wav could be corrupted.
        
        Serial.print("Playing: ");
        Serial.println(entry.name());
           
        while (!wav.isPlaying()) {} // Wait for the header to be read and playback to begin. 
        speaking = 1; // Disable ping and indicate we had a hit.
        
      }
              
    }

Am I doing something wrong here? I tried this both with and without audio interrupts disabled, and both with an without reopening the root directory every time. It takes a while to crash. It plays maybe 10-20 files before it does, usually.

After it gets a hit it waits until wav.isplaying() is false before checking to see if it should play a new file.

I'm not closing any files. I don't know if I need to do that or not. The examples never seem to, and I'm just reading the filenames. I guess I'll try that next.

Oh, I should mention, when it crashes, it never gets to this line:
Serial.print("Playing: ");

The last thing it does is print a filename. So I think it's the call to wav.play(entry.name()) which is failing.
 
Last edited:
Well, it doesn't seem to be the call to wav.play() that's doing it. I added another debug line after the for loop and before and after the reenabling of the audio interrrupt, and neither of those prints. So the crash is in the for loop.

And it seems to be a memory leak... I used the FreeRam() function in SDfatutil.h, and it just keeps going down until it's negative, and then it crashes.
 
Status
Not open for further replies.
Back
Top