The sound of a motor humming on a teensy 3.2

Status
Not open for further replies.

Ced_Sylvain_&_cie

Active member
Dear members of the forum,
I just received my Teensy 3.2 with the audio shield. I soldered everything, and then did the first tests with the Arduino IDE samples. What a joy to see that everything works the first time. I already used Teensy and had some setbacks with the SPI while I started in microelectronics. But it was before.
Here is my question: I registered the engine of my car with my phone. There are several files: the startup when I put the contact. An acceleration and several stable sounds at different speeds.
I would like to create a program that mimics the sound of an engine. I want to limit the number of files to use. Except when I turn on and I turn off the engine, I want to use the same sound file.
For this I am willing to use digital filters, but my knowledge in this area is very limited. Could you point me?

Here's what I noticed, accelerating the engine runs faster and pulls the treble.
Optional: the engine hums sometimes, a little as if at low frequencies it iscillate slightly.

Best regards,
Sylvain.

P.S. If my project materializes, would it be possible to make it appear on the blog? With photos and videos to support.
 
While doing research, I realized that an engine was not only a sound but a set of distinct sounds as clutches, valves ... and for the V8, it emits a very special explosion sound. Would you know where I can find this type of sound? It will be easier for me to assemble them with the Teensy. If you also had paper documentation on the topic could you communicate them to me?
 
Ok Beware the dog ;) I understand the way it mean, lot of sound.wav or Sd??

I ve put the wav file into my sd card, if I change the format into *.mp3, do I have the same results? then i may ask if those libs are similare?
 
Using MP3s is probably not a good idea trying to mix a lot of samples together. Wav files have no compression so they are easier to unpack and stream from the SD card and the total amount of audio here is pretty small. In fact for this you may find converting some of your engine effects to raw and storing them in your program gets the lowest latency with trying to mix the various bits and bobs together. Have not seen a really good solution to what you are trying to do, since ideally you would be tampering with the replay rate and that is not something supported out of the box on Teensy Audio library. So you would be trying to extract the various effects and then firing them off at your engine RPM + mixing in the background mechanical noises on longer loops. You may find using a desktop sound engine may make this sort of thing easier to get your head around and make sure your samples actually mix the way you want.

I have used supercollider https://supercollider.github.io/ but it is massivly overkill for what you want and has a vertiginous learning curve. I was actually looking at a similar task and worked from https://en.wikibooks.org/wiki/Designing_Sound_in_SuperCollider/Cars to synthetically make an gunfire effect, fully building all the elements. Which was fun but the end result was not actually that good so if lining clips up does what you want it will get you there a lot faster than the synth way.
 
I am in the process to emulate engine sounds by modelling the mechanics of the metal and the environment. This most probably will nothing a small micro processor can synthesize in real time, but i cann give you some hints:

- use a dirac impulse shaped with eqs to model the explosions
- superimpose several explosions to shape the real explosion's waves
- add reflections caused by the small room in an engine's parts using a 3D model and reflection zones
- starting from any reflection zone (wall of an engine's part) progress the waves taking the sound speed in metal into account
- add reflections and the end points of all joints, cranks and enclosure parts
- then it comes to damping and EQ-ing to model the losses in the materials and the air.
 
Hello
Thanks for your reply, nevertheless I am a little lost by the techniques you use. In the first step you talk about Dirac and equations which I have no idea of their content.
The second step is okay, I could create a random way to start the sound with defined statistical characteristic, it takes a little work but it is possible.
Then, I'm not sure I understood, the engine being in a reduced space you talk about reflections, then I propose to use the reverberation to have a more realistic rendering?
Fourth point: I have done pretty well by breaking down a short extract of engine sound with three filters, pass low, pass band, and pass high, and superimposing them. So I happen to have a sound rather good.
Fifth point, I do not know, I could understand better with readings.

I would like to try tomorrow to play with the sample rate of a sample in order to vary the speed of the engine. I do not think it will work but I have no other leads at the moment. If you could help me, I tell you what I have to realize:
For now, simulate a single gear with a potentiometer for the throttle. A teensy, a speaker.
 
What Audioengineer is doing is similar to the supercollider link above, producing a burst of noise, filtering it to match an explosive pulse and then adding reverb and mechanical effects.

To achieve a gunfire effect in the teensyaudio system I have used a white noise generator low pass filtered and with the gain sharply ramped up and down to produce the base burst, then added reverb. To this I added a pair of https://www.pjrc.com/teensy/gui/?info=AudioSynthSimpleDrum sythdrum triggers adjusted for a 'ting' sound for the mechanical motion effects. I played around with other effects on the result but generally just made the sound 'flatter'.

So if you want a not very pretty but infinitly adjustable 'bang bang bang' engine noise ASAP my thought would be to grab the white noise source, work out your virtual RPM and write some code to ramp the noise generator amplitude in bursts coming at your virtual RPM.

If you have time you then put a bandpass filter in front to get things more engine like, and with more time change the filter values across X different presets where X is your cylinder number. Sticking some other mechanical noises from strings or drums in there will add some colour and a modulated low rumble would round it out.

The difficulty with this approach is that I do not think a teensy has the capability to produce a truly realistic engine effect from this mechanism since it needs tuned echos as described by audioengineer that if done from first principles would need more processing than a Teensy has.

What this may give you is good enough soon enough.
 
Dusted off some assorted code fragments and and evening's work got this
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthNoiseWhite     noise1;         //xy=127,377
AudioSynthToneSweep      tonesweep1;     //xy=170,246
AudioSynthKarplusStrong  string1;        //xy=182,205
AudioSynthKarplusStrong  string2;        //xy=192,286
AudioSynthSimpleDrum     drum1;          //xy=196,173
AudioFilterBiquad        biquad1;        //xy=297,407
AudioMixer4              mixer1;         //xy=470,258
AudioMixer4              mixer2;         //xy=567,373
AudioOutputI2S           i2s1;           //xy=780,354
AudioOutputAnalog        dac1;           //xy=819,179
AudioConnection          patchCord1(noise1, 0, mixer2, 1);
AudioConnection          patchCord2(noise1, biquad1);
AudioConnection          patchCord3(tonesweep1, 0, mixer1, 2);
AudioConnection          patchCord4(string1, 0, mixer1, 1);
AudioConnection          patchCord5(string2, 0, mixer1, 3);
AudioConnection          patchCord6(drum1, 0, mixer1, 0);
AudioConnection          patchCord7(biquad1, 0, mixer2, 2);
AudioConnection          patchCord8(mixer1, 0, mixer2, 0);
AudioConnection          patchCord9(mixer2, dac1);
AudioConnection          patchCord10(mixer2, 0, i2s1, 0);
AudioConnection          patchCord11(mixer2, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=504,604
// GUItool: end automatically generated code

// GUItool: end automatically generated code

uint32_t cylinder=0;
uint32_t stage=0;
uint32_t cylinderfreq[]= {60,63,58,64,59,60,58,61,62};
elapsedMillis sinceBang;
elapsedMillis sinceStatus;
byte bangStage =0;
uint32_t bangPeriodMilliseconds = 500;
void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);

  // audio library init
  AudioMemory(15);

 

  AudioNoInterrupts();

  drum1.frequency(60);
  drum1.length(1500);
  drum1.secondMix(0.0);
  drum1.pitchMod(0.55);
  mixer2.gain(1,0);
 //  mixer2.gain(1,0);
  biquad1.setLowpass(0,400,0.8);
  
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.6);

  AudioInterrupts();

}

void loop() {
  // put your main code here, to run repeatedly:

  //these numbers would be better being adjusted as RPM increases
  if (bangStage==1) if (sinceBang>50){noise1.amplitude(0.1); bangStage=2; }
  if (bangStage==2) if (sinceBang>100){noise1.amplitude(0.5); bangStage=3; }
  if (bangStage==3) if (sinceBang>50){noise1.amplitude(0.000); bangStage=0; }
 
  if(sinceBang>bangPeriodMilliseconds)    
  {
    sinceBang=0;
    bangStage=1;
    cylinder++;
    if (cylinder>7) cylinder=0;
    drum1.frequency(cylinderfreq[cylinder]);
      drum1.length(bangPeriodMilliseconds);
    drum1.noteOn();
    noise1.amplitude(0.05);
    stage++;

    //add your own RPM process here
    if (stage>100) stage=0;
    if (stage<50)bangPeriodMilliseconds=300-stage*4;
    else bangPeriodMilliseconds=300-(100-stage)*4;
    //End of cut for RPM code

 
  }
  if (sinceStatus>5000){
    Serial.print("Diagnostics: ");
    Serial.print(AudioProcessorUsageMax());
    Serial.print(" ");
    Serial.println(AudioMemoryUsageMax());
    AudioProcessorUsageMaxReset();
  }
}
Should be outputting both to audio shield headset and the teensy DAC. Several things wrong with it, including several unused instruments and realism close to zero but does function. I think next step is to double up the drums, possibly to one per cylinder so they have more time between beats and simplify pitch shifting them.
 
Okay, I can see more clearly. I'm doing tests today. I'll send you a code tonight.
And thanks to you GreemlinWrangler for your code, i'll try it now
 
Hello
Here's the GremlinWrangler program test. I changed some settings and I find the result very good. Now, to improve this code, I will add a more explosive "bang", simulating the explosion of gasoline in the engine, I would like to filter the sound of the engine again to get a more metallic rendering.
If you have some other tricks, please send them to me:)


Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioSynthNoiseWhite     noise1;         //xy=127,377
AudioSynthSimpleDrum     drum1;          //xy=196,173
AudioFilterBiquad        biquad1;        //xy=297,407
AudioMixer4              mixer1;         //xy=470,258
AudioMixer4              mixer2;         //xy=567,373
AudioOutputI2S           i2s1;           //xy=780,354
AudioEffectFreeverb      freeverb1;
AudioConnection          patchCord1(noise1, 0, mixer2, 1);
AudioConnection          patchCord2(noise1, biquad1);
AudioConnection          patchCord6(freeverb1, 0, mixer1, 0);
AudioConnection          patchCord7(biquad1, 0, mixer2, 2);
AudioConnection          patchCord8(mixer1, 0, mixer2, 0);
AudioConnection          patchCord9(drum1,freeverb1 );
AudioConnection          patchCord10(mixer2, 0, i2s1, 0);
AudioConnection          patchCord11(mixer2, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=504,604
// GUItool: end automatically generated code

// GUItool: end automatically generated code

uint32_t cylinder=0;
uint32_t cylinderfreq[]= {60,63,58,80,59,60,50,61,62};
elapsedMillis sinceBang;
elapsedMillis sinceStatus;
byte bangStage =0;
uint32_t bangPeriodMilliseconds = 500;
void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);

  // audio library init
  AudioMemory(15);

 

  AudioNoInterrupts();

  drum1.frequency(60);
  drum1.length(1500);
  drum1.secondMix(0.0);
  drum1.pitchMod(0.55);
  mixer2.gain(1,0);
  biquad1.setLowpass(0,1200,0.8);
  
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.6);

  AudioInterrupts();

}

void loop() {
  // put your main code here, to run repeatedly:
      freeverb1.roomsize(0.4);
      freeverb1.damping(4);
      
  //these numbers would be better being adjusted as RPM increases
  if (bangStage==1) if (sinceBang>50){noise1.amplitude(0.08); bangStage=2; }
  if (bangStage==2) if (sinceBang>100){noise1.amplitude(0.5); bangStage=3; }
  if (bangStage==3) if (sinceBang>50){noise1.amplitude(0.000); bangStage=0; }
 
  if(sinceBang>bangPeriodMilliseconds)    
  {
    sinceBang=0;
    bangStage=1;
    cylinder++;
    if (cylinder>7) cylinder=0;
    drum1.frequency(cylinderfreq[cylinder]+20);
      drum1.length(bangPeriodMilliseconds);
    drum1.noteOn();
    noise1.amplitude(0.05);
   

    //add your own RPM process here
  
    bangPeriodMilliseconds=70;
   // 
 
  }
  if (sinceStatus>5000){
    Serial.print("Diagnostics: ");
    Serial.print(AudioProcessorUsageMax());
    Serial.print(" ");
    Serial.println(AudioMemoryUsageMax());
    AudioProcessorUsageMaxReset();
  }
}

Thank you for your help
 
Well one thing to look at is my code has an error at
if (bangStage==3) if (sinceBang>50){noise1.amplitude(0.000); bangStage=0; }

That would probably work better if it was

if (bangStage==3) if (sinceBang>150){noise1.amplitude(0.000); bangStage=0; }
Otherwise it fires oce cycle after sinceBang==100
 
I found accidentally a method to simulate the sound of the engine start-up.

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
int R=0;
long t0=0;
// GUItool: begin automatically generated code
AudioSynthNoiseWhite     noise2;         //xy=352,1067
AudioSynthWaveform waveform;   //xy=353,1136
AudioFilterBiquad        biquad2;        //xy=633,1052
AudioEffectMultiply      multiply1;      //xy=869,1093
AudioEffectFreeverb      freeverb1;
AudioEffectDigitalCombine combine1;
AudioOutputI2S           i2s2;           //xy=1076,1097
AudioConnection          patchCord1(noise2, biquad2);
AudioConnection          patchCord2(waveform, 0, multiply1, 1);
AudioConnection          patchCord3(biquad2, 0, multiply1, 0);
AudioConnection          patchCord4(multiply1, 0, freeverb1, 0);
AudioConnection          patchCord5(freeverb1, 0, i2s2, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=880,644
// GUItool: end automatically generated code



void setup() {
     Serial.begin(115200);
     // audio library init
     AudioMemory(15);
     AudioNoInterrupts();
     biquad2.setBandpass(0,1000,0.8);
     waveform.frequency(10);
     sgtl5000_1.enable();
     sgtl5000_1.volume(0.6);
     waveform.amplitude(1);
     AudioInterrupts();
     long t0=millis();
}

void loop() {
     if (millis()<t0+2500){
          freeverb1.roomsize(0.01);
          freeverb1.damping(10);
          noise2.amplitude(1);
          waveform.begin(WAVEFORM_PULSE);waveform.offset(-1);  waveform.pulseWidth(0.90);
   }

else {noise2.amplitude(0);}

}
 
The following point is still a mystery for me:
starting from any reflection zone (wall of an engine's part) progress the waves taking the sound speed in metal into account
I understand the sentence but not how to achieve it, could explain me this further?
 
Materials have different speed of sound values so a true engine model would be spreading the impulse noise spectrum from each cylinder fire similar to these things
https://en.wikipedia.org/wiki/Surface_acoustic_wave_sensor
In teensy Audio terms this would be a chain of delay units with a narrow filter on each join in the chain and then the filter outputs mixed together. This would allow some parts of the spectrum to arrive sooner than others. This would be very processor intensive and might make sense in a simulated instrument but not seeing any particular parts of an engine note that would benefit from it.

I suspect what we need now is something that simulates the whistle/whoosh noise from the exhaust air, which I think starts as a sine fm object but at the moment unclear on how to modulate that.
 
Hello
I made several changes to the code:
- A PID regulator for throttle control
- The noise is simulated by the envelope function, interesting!
- Added a random function for the frequencies of the cylinders, before that created a cyclic melody a bit annoying
- A Drum Time Extension that smoothing the sound.

To GremlinWrangler:
I suspect what we need now is something that simulates the whistle/whoosh noise

You can check the code and put :
mixer2.gain(0,0);
mixer2.gain(1,1); // gain du bruit du moteur
mixer2.gain(2,0); // gain des cylindres

In order to hear the whistle noise. Do you agree ?



Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>



AudioSynthNoiseWhite     noise1;         //xy=696,304
AudioEffectEnvelope      envelope1;      //xy=847,309
AudioEffectFreeverb      freeverb1;
AudioMixer4              mixerBang;
AudioSynthSimpleDrum     drum1;  
AudioFilterBiquad        biquad1;
AudioFilterBiquad        biquad2;        //xy=297,407
AudioFilterBiquad        biquad3;        //xy=297,407
AudioMixer4              mixer2;         //xy=567,373
AudioSynthKarplusStrong  string1;        //xy=182,205
AudioOutputI2S           i2s1;           //xy=1074,309

AudioConnection          patchCord1(noise1, biquad1);
AudioConnection          patchCord2(drum1,biquad2);
AudioConnection          patchCord3( biquad1,envelope1);
AudioConnection          patchCord4(envelope1,freeverb1 );
AudioConnection          patchCord5(string1, biquad3);
AudioConnection          patchCord6(biquad2, 0,mixer2, 2);
AudioConnection          patchCord7(biquad3, 0, mixer2, 0);
AudioConnection          patchCord8(freeverb1, 0, mixer2, 1);
AudioConnection          patchCord9(mixer2, 0, i2s1, 0);
AudioConnection          patchCord10(mixer2, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=504,604

const int sensorPin = A2;
uint32_t cylinder=0;
uint32_t cylinderfreq[]= {60,63,58,56,59,60,60,61,62};
static  float bangPeriodMilliseconds = 50;

// Variables PID
static float P, I,D;
float oldBang=0;static float commande;int sensorValue;

//Variables temporelles
static uint32_t next;static uint32_t old;
elapsedMillis sinceBang;
elapsedMillis delayBang;
elapsedMillis sinceStatus;

void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  // audio library init
  AudioMemory(15);
  AudioNoInterrupts();

  mixer2.gain(0,2);
  mixer2.gain(1,2);  // gain du bruit du moteur
  mixer2.gain(2,2); // gain des cyilindres
  drum1.secondMix(0);
  drum1.pitchMod(0);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.9);
  biquad1.setLowpass(0,300,0.8);
  biquad2.setLowpass(0,180,0.8);
  biquad3.setLowpass(0,200,0.8);
    noise1.amplitude(0.15);
envelope1.attack(25);
envelope1.hold(20);
envelope1.decay(150);
envelope1.sustain(0.4);
envelope1.release(300);
freeverb1.roomsize(0.1);
freeverb1.damping(1);
  AudioInterrupts();

}

void loop() {
    next = millis();
  
    //Start RPM code
if (next-old>100){
old=millis();
 sensorValue = analogRead(sensorPin);
 commande =map(sensorValue,1,1024,16,100);
 P=0.6;I=0.8;D=0.3;
oldBang=bangPeriodMilliseconds;
bangPeriodMilliseconds = (commande - bangPeriodMilliseconds)*(P);
bangPeriodMilliseconds = commande - D*abs(bangPeriodMilliseconds-oldBang);
bangPeriodMilliseconds = commande - I*(commande - oldBang);
}
   //end RPM code

 
  if(sinceBang>bangPeriodMilliseconds)    
  {
   
 int rdm_cylinder=random(0,8);
    
    sinceBang=0;
    drums(cylinderfreq[rdm_cylinder],bangPeriodMilliseconds);
    noise();


  }
  AudioInterrupts();
 
  if (sinceStatus>5000){

    Serial.print("     Diagnostics: ");
    Serial.print(AudioProcessorUsageMax());
    Serial.print(" ");
    Serial.println(AudioMemoryUsageMax());
    AudioProcessorUsageMaxReset();
  }
  

}
void drums(int cylinder, int length){
  drum1.frequency(cylinder);
  drum1.length(length+90);
  drum1.noteOn();

}

void noise()
{
   envelope1.noteOn();
   envelope1.noteOff();
}
 
Last edited:
I put a multiply block between the sound created by the cylinders/blasts and a sine. The result is much better at low speed, I'm happy! Nevertheless the whole lack of realism at high speed. Did I forget Something?
 
Have not had a chance to run up your rebuilt code yet, but suspect there is the exhaust note thing that becomes much more significant as the RPM reaches the point that individual exhaust pulses start to blend together.

Edit: have now got the code running on my hardware and it is much better with the 'fuzz' but as you say still artificial, sounding more like an electric motor and an internal combustion engine.
 
Last edited:
Now i think it's better, still missing the exhaust pipe and we done!


Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>



AudioSynthNoiseWhite     noise1;         //xy=696,304
AudioEffectEnvelope      envelope1;      //xy=847,309
AudioEffectFreeverb      freeverb1;
AudioMixer4              mixerBang;
AudioSynthSimpleDrum     drum1;
AudioSynthWaveformSineModulated  Sine1;  
AudioFilterBiquad        biquad1;
AudioFilterBiquad        biquad2;        //xy=297,407
AudioFilterBiquad        biquad3;        //xy=297,407
AudioMixer4              mixer2;         //xy=567,373
AudioSynthKarplusStrong     drum2;        //xy=182,205
AudioOutputI2S           i2s1;           //xy=1074,309
AudioEffectMultiply      mult1;
AudioConnection          patchCord1(noise1, biquad1);
AudioConnection          patchCord2(drum1,biquad2);
AudioConnection          patchCord3( biquad1,envelope1);
AudioConnection          patchCord4(envelope1,freeverb1 );
AudioConnection          patchCord5(Sine1, biquad3);
AudioConnection          patchCord6(biquad2, 0,mixer2, 2);
AudioConnection          patchCord7(biquad3, 0, mult1, 1);
AudioConnection          patchCord8(freeverb1, 0, mixer2, 1);
AudioConnection          patchCord9(mixer2, 0, mult1,0);
AudioConnection          patchCord11(mult1, 0, i2s1, 0);
AudioConnection          patchCord12(mult1, 0, i2s1, 1);

AudioControlSGTL5000     sgtl5000_1;     //xy=504,604

const int sensorPin = A2;
uint32_t cylinder=0;
uint32_t cylinderfreq[]= {60,63,58,56,59,60,60,61,62};
int F,S,BP;
static int bangPeriodMilliseconds = 50;

// Variables PID
static float P, I,D;
float oldBang=0;static float commande;int sensorValue;

//Variables temporelles
static uint32_t next;static uint32_t old;
elapsedMillis sinceBang;
int delayBang;
elapsedMillis sinceStatus;

void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  // audio library init
  AudioMemory(15);
  AudioNoInterrupts();

  mixer2.gain(0,2);
  mixer2.gain(1,2);  // gain du bruit du moteur
  mixer2.gain(2,2); // gain des cyilindres
  drum1.secondMix(0);
  drum1.pitchMod(0.5);
  
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.9);
  biquad1.setLowpass(0,300,0.8);
  biquad2.setLowpass(0,250,0.8);
  biquad3.setLowpass(0,200,0.8);

envelope1.attack(25);
envelope1.hold(20);
envelope1.decay(150);
envelope1.sustain(0.4);
envelope1.release(300);
freeverb1.roomsize(0.1);
freeverb1.damping(1);
Sine1.amplitude(0.5);
  AudioInterrupts();

}

void loop() {
    next = millis();
   
    //Start RPM code
if (next-old>100){
old=millis();
 sensorValue = analogRead(sensorPin);
 commande =map(sensorValue,1,1024,12,100);
 P=0.6;I=0.8;D=0.3;
oldBang=bangPeriodMilliseconds;
bangPeriodMilliseconds = (commande - bangPeriodMilliseconds)*(P);
bangPeriodMilliseconds = commande - D*abs(bangPeriodMilliseconds-oldBang);
bangPeriodMilliseconds = commande - I*(commande - oldBang);
}
   //end RPM code

reglages(bangPeriodMilliseconds);
 
  if(sinceBang>bangPeriodMilliseconds)    
  {
   
 int rdm_cylinder=random(0,8);
    Serial.println(bangPeriodMilliseconds);
    sinceBang=0;
    drums(cylinderfreq[rdm_cylinder]+F,bangPeriodMilliseconds+P);// ou F un reglage pour augmenter la freq des cylindres,
    noise(0.35);                                                 // ou P pour la prolongation du bruit 
    Sine1.frequency(S);                                          // ou S pour la freq du vibrement moteur   
    
  }

//bangPeriodMilliseconds = map(sensorValue,1,1024,16,100);

  AudioInterrupts();
 
  if (sinceStatus>500){

    Serial.print("     Diagnostics: ");
    Serial.print(AudioProcessorUsageMax());
    Serial.print(" ");
    Serial.println(AudioMemoryUsageMax());
    AudioProcessorUsageMaxReset();
    sinceStatus=0;
  }
  

}
void drums(int cylinder, int length){
  drum1.frequency(cylinder);
  drum1.length(length+4);
  drum1.noteOn();
}

void noise(int amplitude)
{
    noise1.amplitude(amplitude);
   envelope1.noteOn();
   envelope1.noteOff();
}

void reglages( int bangPeriod ) {
if (bangPeriod>=80){
F=0;
BP=120;
S=random(7,90);
}
if (bangPeriod>=60 || bangPeriod<80 ){
F=5;
BP=15;
S=12;
}

if (bangPeriod>40 || bangPeriod<60 ){
F=13;
BP=70;
S=9;
}

if (bangPeriod>=20 || bangPeriod<40 ){
F=15;
BP=5;
S=10;
}

if (bangPeriod<20 ){
F=20;
BP=5;
S=8;

}

}
 
could you check this sound?

Hello,
With some usefull tips, I made the sound of a motor. The engine go from 500RPM to 4000RPM.
Here is the diagram made with pjrc audio library. if you want to hear the sound you need a potentiometer or change bangPeriodMilliseconds manually.

Capture_teensy.PNG
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthNoiseWhite     noise2;         
AudioSynthNoiseWhite     noise1;         
AudioSynthSimpleDrum     drum1;          
AudioSynthWaveform       waveform_start; 
AudioSynthWaveformDc     dc1;        
AudioFilterBiquad        biquad2;    
AudioFilterBiquad        biquad1;    
AudioFilterBiquad        biquad3;    
AudioEffectEnvelope      envelope1;  
AudioEffectMultiply      multiply2;  
AudioEffectMultiply      mult2;      
AudioMixer4              mixer2;      
AudioEffectFreeverb      freeverb1;    
AudioSynthWaveformSineModulated Sine1;  
AudioEffectFreeverb      freeverb2;     
AudioEffectMultiply      mult1;         
AudioMixer4              mixerBang;     
AudioAmplifier           amp1;          
AudioOutputI2S           i2s1;          
AudioConnection          patchCord1(noise2, biquad3);
AudioConnection          patchCord3(noise1, biquad1);
AudioConnection          patchCord4(drum1, biquad2);
AudioConnection          patchCord5(waveform_start, 0, multiply2, 0);
AudioConnection          patchCord6(dc1, 0, mult2, 1);
AudioConnection          patchCord7(biquad2, 0, mixer2, 1);
AudioConnection          patchCord8(biquad1, envelope1);
AudioConnection          patchCord9(biquad3, 0, mult2, 0);
AudioConnection          patchCord10(biquad3, 0, multiply2, 1);
AudioConnection          patchCord11(envelope1, 0, mixer2, 0);
AudioConnection          patchCord12(multiply2, 0, mixer2, 2);
AudioConnection          patchCord13(mult2, freeverb2);
AudioConnection          patchCord14(mixer2, freeverb1);
AudioConnection          patchCord15(freeverb1, 0, mult1, 0);
AudioConnection          patchCord16(Sine1, 0, mult1, 1);
AudioConnection          patchCord17(freeverb2, 0, mixerBang, 1);
AudioConnection          patchCord18(mult1, 0, mixerBang, 0);
AudioConnection          patchCord19(mixerBang, amp1);
AudioConnection          patchCord20(amp1, 0, i2s1, 0);
AudioConnection          patchCord21(amp1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     


//#define COMM_ROUE     A0//channel 1


const int sensorPin = A2;
uint32_t cylinder=0;
uint32_t cylinderfreq[]= {60,63,58,56,59,60,60,61,62};
int F,S,BP;
float G;
static int bangPeriodMilliseconds = 100;

// Variables PID
static float P, I,D;
float oldBang=0;static float commande;int sensorValue;

//Variables temporelles
static uint32_t next;static uint32_t old;
elapsedMillis sinceBang;
int delayBang;
elapsedMillis sinceStatus;
static int bpms = 0;

void setup() {
  // put your setup code here, to run once:
  
  Serial.begin(9600);
    
  // pinMode(COMM_ROUE, INPUT);
    
  AudioMemory(15);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.7);
  mixer2.gain(0,0);
  mixer2.gain(1,10);  // gain du bruit du moteur
  mixer2.gain(2,0);
  mixer2.gain(3,0);
  mixerBang.gain(0,1);// gain des cyilindres
  mixerBang.gain(1,0);
  biquad1.setLowpass(0,200,0.8);
  biquad2.setLowpass(0,250,0.8);
  biquad3.setBandpass(0,1000,0.8);
  
  amp1.gain(2);
    
  envelope1.attack(25);
  envelope1.hold(20);
  envelope1.decay(150);
  envelope1.sustain(0.05);
  envelope1.release(100);

  freeverb1.roomsize(0.2);
  freeverb1.damping(1);
  freeverb2.roomsize(0.01);
  freeverb2.damping(0.1);

  Sine1.amplitude(2);
  Sine1.frequency(-1);
  Sine1.phase(90);
  
  drum1.secondMix(0.5);
  drum1.pitchMod(0.5);
  noise2.amplitude(5);
  
  waveform_start.frequency(8);
  waveform_start.amplitude(1);
  waveform_start.begin(WAVEFORM_SQUARE);
 
  while (millis()<2000){
    freeverb1.roomsize(0.4);
    freeverb1.damping(1);
    noise2.amplitude(1);
    waveform_start.begin(WAVEFORM_PULSE);waveform_start.offset(-1);  waveform_start.pulseWidth(0.90);
    }
  noise2.amplitude(0);
  waveform_start.amplitude(0);
}

void loop() {

//long duration = pulseIn(COMM_ROUE, HIGH);
//long commande =map(duration,1438,1179,110,20);
  AudioInterrupts();
  next = millis();
  if (next-old>100){
    if ( bpms != bangPeriodMilliseconds ) {
      bpms = bangPeriodMilliseconds;
      Serial.println(bangPeriodMilliseconds);
    }
    old=millis();
    sensorValue = analogRead(sensorPin);
    commande =map(sensorValue,1,1024,12,100);
 
    P=0.6;I=0.8;D=0.3;
    oldBang=bangPeriodMilliseconds;
    bangPeriodMilliseconds = (commande - bangPeriodMilliseconds)*(P);
    bangPeriodMilliseconds = commande - D*abs(bangPeriodMilliseconds-oldBang);
    bangPeriodMilliseconds = commande - I*(commande - oldBang);
  }

  reglages(bangPeriodMilliseconds);
 
  if(sinceBang>bangPeriodMilliseconds)    
    {
    int    rdm_explos=random(1,35);
    if(rdm_explos==5)
       dc1.amplitude(2,1);
    else
       dc1.amplitude(0,1);
    int rdm_cylinder=random(0,8);
    sinceBang=0;
    drums(cylinderfreq[rdm_cylinder]+F,bangPeriodMilliseconds+BP);// ou F un reglage pour augmenter la freq des cylindres,
    noise(1.5);                                                 // ou P pour la prolongation du bruit 
    Sine1.frequency(S);                                          // ou S pour la freq du vibrement moteur   
    amp1.gain(G);
   }



//bangPeriodMilliseconds = map(sensorValue,1,1024,16,100);

  AudioInterrupts();
 
        noise2.amplitude(1);
//    waveform.begin(WAVEFORM_PULSE);waveform.offset(-1);  waveform.pulseWidth(0.95);
  if (sinceStatus>500){
    Serial.print("     Diagnostics: ");
    Serial.print(AudioProcessorUsageMax());
    Serial.print(" ");
    Serial.println(AudioMemoryUsageMax());
    AudioProcessorUsageMaxReset();
    sinceStatus=0;
  }
  

}
void drums(int cylinder, int length){
  drum1.frequency(cylinder);
  drum1.length(length);
  drum1.noteOn();
}

void noise(int amplitude)
{
  noise1.amplitude(amplitude);
  envelope1.noteOn();
  envelope1.noteOff();
}

void reglages( int bangPeriod ) {
  if (bangPeriod>=90){
    freeverb1.roomsize(0.7);
    freeverb1.damping(1);
    biquad1.setBandpass(0,250,0.8);
    biquad2.setBandpass(0,600,0.8);
    F=20;
    BP=100;
    S=11;
    G=0.5;
  }

  if (bangPeriod>=60 && bangPeriod<90 ){
    biquad1.setBandpass(0,250,0.8);
    biquad2.setHighpass(0,190,1.4);
    F=25;
    BP=100;
    S=13;
    G=0.8;
  }

  if (bangPeriod<60 ){
    // freeverb1.roomsize(0.7);
    //  freeverb1.damping(1);
    biquad1.setBandpass(0,250,0.8);
    biquad2.setBandpass(0,200,2);
    F=25;
    BP=3;
    S=11;
    G=1;
    }
}
 
Last edited:
There is still something wrong, I'd like to put a function "pulseIn()" but there is a conflict with "AudioMemory(15)"
In fact, when pulsein() is called without audioMemory my fonction works fine, but i can't get any sound. as the opposite i have good sound but pulseIn() gives an erratic long response.

I think a conflict with interrupts is happening but no way to resolve it…
 
Status
Not open for further replies.
Back
Top