Comments (8)
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.
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.
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.
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.
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.
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.
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.
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)
- Compilation errors when including both WaveFolder.h and ResonantFilter.h HOT 3
- Unable to compile for Atmega328PB with Arduino IDE HOT 3
- Sample example not working on UNO R4 HOT 11
- Arduino Nano 33 IoT tested and works with the output on DAC0, which is also called A0 HOT 2
- Output frequency 0.25% off on AVRs HOT 1
- RFC: Mozzi 2.0 part 1: Single compilation unit HOT 7
- RFC: Mozzi 2.0 part 2 - Configuration restructuring HOT 7
- Improving fixMath HOT 5
- Please Change Mozzi's License HOT 10
- Using Mozzi and I2C library for LCD HOT 14
- RFC: Mozzi 2.0 part 3 - Miscellanious
- UNO R4 port broken HOT 2
- Compatability/Compilation Issues w/ Nano 33 BLE Sense HOT 5
- Apparent frequency drops when amplitude increased beyond 8 bits on AVR HOT 3
- mozzi_rand cannot go full range HOT 7
- AVR PWM range is not actually 0-488 ("8.5 bit"), but effectively 0-400 HOT 6
- Minor / infrastructure: Avoid duplicate workflow runs on pushes to PRs HOT 1
- I2S dac with a nano. HOT 12
- VS10XX as DAC HOT 38
- RFC: Analog input scaling - what's the best approach HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mozzi.