Code Monkey home page Code Monkey logo

Comments (8)

konsumer avatar konsumer commented on July 4, 2024

Also, it seems like with this code, if I had multiple channels set to TRI, updateAudio() would call next() several times, which would mess up the phase, right?

from mozzi.

konsumer avatar konsumer commented on July 4, 2024

Here is another try (full code example) that seems closer, but it's still re-initializing the wave too much for my taste. I feel like there is some C-thing I am probably forgetting/don't know:

#include <MozziGuts.h>
#include <Oscil.h>
#include <utils.c>
#include <EventDelay.h>

#include <tables/sin512_int8.h>
#include <tables/saw_analogue512_int8.h>
#include <tables/triangle_analogue512_int8.h>
#include <tables/square_analogue512_int8.h>

#define CONTROL_RATE 64

#define SIN 0
#define SAW 1
#define TRI 2
#define SQR 3

#define VOICE_COUNT 4

struct channel{
  byte gain;
  unsigned int freq;
  byte wave;
  byte oldwave;
};

// initialize channels with SIN @ 440Hz
channel channels[VOICE_COUNT] = {0, mtof(60), SIN, SIN};
Oscil<512, AUDIO_RATE> wave_table[VOICE_COUNT] = { Oscil<512, AUDIO_RATE>(SIN512_DATA), Oscil<512, AUDIO_RATE>(SIN512_DATA), Oscil<512, AUDIO_RATE>(SIN512_DATA), Oscil<512, AUDIO_RATE>(SIN512_DATA) };

// audio output
int output;

// generic iterator
byte i = 0;

EventDelay noteDelay(CONTROL_RATE);

void setup(){
  startMozzi(CONTROL_RATE);

  // change 1 channel's freq every second
  noteDelay.set(1000);

  // set wave #'s
  channels[1].wave = SAW;
  channels[2].wave = TRI;
  channels[3].wave = SQR;

  // set freq, so you can tell channels apart
  channels[1].freq = mtof(30);
  channels[2].freq = mtof(45);
  channels[3].freq = mtof(75);

  Serial.begin(9600);
}

void loop(){  
  audioHook();
}

unsigned long randnum;

void updateControl(){
  // update wave tables to refelect channels
  for(i=0;i<VOICE_COUNT;i++){
    if (channels[i].oldwave != channels[i].wave){
      switch(channels[i].wave){
        case SIN: wave_table[i] = Oscil<512, AUDIO_RATE>(SIN512_DATA); break;
        case SAW: wave_table[i] = Oscil<512, AUDIO_RATE>(saw_analogue512_data); break;
        case TRI: wave_table[i] = Oscil<512, AUDIO_RATE>(TRIANGLE_ANALOGUE512_DATA); break;
        case SQR: wave_table[i] = Oscil<512, AUDIO_RATE>(SQUARE_ANALOGUE512_DATA); break;
      }
      channels[i].oldwave = channels[i].wave;
    }
    wave_table[i].setFreq(channels[i].freq);
  }

  // tester code: change 1 channel's freq every second
  if (noteDelay.ready()){
    randnum = xorshift96();
    // offset note changes to make voices easier to tell apart
    for(i=0;i<VOICE_COUNT;i++){
      if (byteMod(randnum, VOICE_COUNT) == i){
        channels[i].gain = 0;
        channels[i].freq = mtof(byteMod(randnum, 48) + (12*i));
        channels[i].gain = 1;
        channels[i].wave = byteMod(randnum, 4);
        noteDelay.start();
        break;
      }
    }
  }
}

int updateAudio(){
  output=0;

  for(i=0;i<VOICE_COUNT;i++){
    if (channels[i].gain != 0){
        output += wave_table[ i ].next() * channels[i].gain;
    }
  }

  return output;
}

from mozzi.

sensorium avatar sensorium commented on July 4, 2024

Hi,
have you tried using pointers/references?
I've had a crack at it like this:

// array of references to initialised tables
Oscil <512, AUDIO_RATE> * wave_tables[NUM_TABLES] ={&sin_table, &tri_table};

// pointer to a table, should work for all if they are the same size
Oscil <512, AUDIO_RATE> * current_table;

// then in updateAudio()....
current_table = wave_tables[i];
out += (*current_table).next();

I think that works (here) - let me know ..

from mozzi.

konsumer avatar konsumer commented on July 4, 2024

I think that would also effect multiple tables when I make changes to 2 voices with same waveform. I think my solution (full code example) gets around that, because each wave_table is a separate Oscil().

from mozzi.

sensorium avatar sensorium commented on July 4, 2024

You are right about calling next() several times on the same Oscil changing the phase -
The way I've approached this is to use a separate Oscil to store each set of variables (ie. phase info!) -- they can read from the same wavetable.
Open to any ideas about other ways / suggestions, etc.

Woops! Just got your last comment!

And I just realised/noticed the initialising the Oscils in updateControl() - does that play? I would have expected it to glitch or freeze...

A simple way might be to save each Oscil's next() value once per update(Audio(), and use this as many times as you want.

I didn't include an Oscil::current() method because I was wary of possible overhead in th extra layer of reference - in my tests, a saving local char is faster if you want to re-use the next() value.

Thanks for the feedback.

from mozzi.

konsumer avatar konsumer commented on July 4, 2024

It seems to play ok, but it is hard to tell with so many channels going. I am working on MIDI, now, so I can have better control of which channels are playing at once. Since the wave-tables change only happens once per change (channel.old_wave) it seems to be ok. I tried it in loop() and updateControl() and it seems fine in both.

from mozzi.

konsumer avatar konsumer commented on July 4, 2024

Ok, after some hefty testing with 4 channels + midi + switching wave-tables a lot, my code sounds a bit jerky (but less than I might have thought!) Even though it's messed up, it sounds kinda cool. I am going to experiment with optimizing by phase.

Feel free to have a look at my experiments : arduino code + output + renoise file I used to send midi.

The hardware is:

  • arduino with an ATMEGA328
  • a lowpass filter (1 res + 1 cap) on arduino pin 9 (audio out) before into my (computer for recording) stereo
  • a midi-in circuit using 6n138, 2 resistors, and 1 diode on RX (pin 0)

from mozzi.

sensorium avatar sensorium commented on July 4, 2024

Great! pasted this topic to https://groups.google.com/forum/#!forum/mozzi-users
the Mozzi-users group, just set up now...

from mozzi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.