Author Topic: Building musical synthesizers and keyboards  (Read 19977 times)

0 Members and 1 Guest are viewing this topic.

Offline BrianHG

  • Super Contributor
  • ***
  • Posts: 7661
  • Country: ca
Re: Building musical synthesizers and keyboards
« Reply #50 on: June 26, 2017, 10:26:01 am »
Found my white noise code.
It's actually a 43 bit LFSR generator xored with a 37 bit CASR random number generator, outputting 16 bits of the 80.  I got the combination years ago from an online university R&D paper so I cannot take the credit for this particular combination which originally was in verilog, but the author did do analysis and repeat-ability of each bit individually and found that this was as random as it gets for it's size of bits.

This is as white as I was able to get, sorry but it's programmed in verilog:

Code: [Select]
module white_noise ( clk, rst, ena, out );

input         clk, rst, ena;
output [15:0] out ;
wire          [15:0] out = number_o[31:16] ;

reg [31:0] number_o;
reg [42:0] LFSR_reg;
reg [36:0] CASR_reg;

//CASR:
reg[36:0] CASR_varCASR,CASR_outCASR;
always @(posedge clk )
   begin

   if ( rst )
      begin
        CASR_reg  = (1);
      end
   else
      begin

         if (ena) begin

         CASR_varCASR =CASR_reg ;

         CASR_outCASR [36]=CASR_varCASR [35]^CASR_varCASR [0];
         CASR_outCASR [35]=CASR_varCASR [34]^CASR_varCASR [36];
         CASR_outCASR [34]=CASR_varCASR [33]^CASR_varCASR [35];
         CASR_outCASR [33]=CASR_varCASR [32]^CASR_varCASR [34];
         CASR_outCASR [32]=CASR_varCASR [31]^CASR_varCASR [33];
         CASR_outCASR [31]=CASR_varCASR [30]^CASR_varCASR [32];
         CASR_outCASR [30]=CASR_varCASR [29]^CASR_varCASR [31];
         CASR_outCASR [29]=CASR_varCASR [28]^CASR_varCASR [30];
         CASR_outCASR [28]=CASR_varCASR [27]^CASR_varCASR [29];
         CASR_outCASR [27]=CASR_varCASR [26]^CASR_varCASR [27]^CASR_varCASR [28];
         CASR_outCASR [26]=CASR_varCASR [25]^CASR_varCASR [27];
         CASR_outCASR [25]=CASR_varCASR [24]^CASR_varCASR [26];
         CASR_outCASR [24]=CASR_varCASR [23]^CASR_varCASR [25];
         CASR_outCASR [23]=CASR_varCASR [22]^CASR_varCASR [24];
         CASR_outCASR [22]=CASR_varCASR [21]^CASR_varCASR [23];
         CASR_outCASR [21]=CASR_varCASR [20]^CASR_varCASR [22];
         CASR_outCASR [20]=CASR_varCASR [19]^CASR_varCASR [21];
         CASR_outCASR [19]=CASR_varCASR [18]^CASR_varCASR [20];
         CASR_outCASR [18]=CASR_varCASR [17]^CASR_varCASR [19];
         CASR_outCASR [17]=CASR_varCASR [16]^CASR_varCASR [18];
         CASR_outCASR [16]=CASR_varCASR [15]^CASR_varCASR [17];
         CASR_outCASR [15]=CASR_varCASR [14]^CASR_varCASR [16];
         CASR_outCASR [14]=CASR_varCASR [13]^CASR_varCASR [15];
         CASR_outCASR [13]=CASR_varCASR [12]^CASR_varCASR [14];
         CASR_outCASR [12]=CASR_varCASR [11]^CASR_varCASR [13];
         CASR_outCASR [11]=CASR_varCASR [10]^CASR_varCASR [12];
         CASR_outCASR [10]=CASR_varCASR [9]^CASR_varCASR [11];
         CASR_outCASR [9]=CASR_varCASR [8]^CASR_varCASR [10];
         CASR_outCASR [8]=CASR_varCASR [7]^CASR_varCASR [9];
         CASR_outCASR [7]=CASR_varCASR [6]^CASR_varCASR [8];
         CASR_outCASR [6]=CASR_varCASR [5]^CASR_varCASR [7];
         CASR_outCASR [5]=CASR_varCASR [4]^CASR_varCASR [6];
         CASR_outCASR [4]=CASR_varCASR [3]^CASR_varCASR [5];
         CASR_outCASR [3]=CASR_varCASR [2]^CASR_varCASR [4];
         CASR_outCASR [2]=CASR_varCASR [1]^CASR_varCASR [3];
         CASR_outCASR [1]=CASR_varCASR [0]^CASR_varCASR [2];
         CASR_outCASR [0]=CASR_varCASR [36]^CASR_varCASR [1];

         CASR_reg  = (CASR_outCASR );

         end
      end
   end

//LFSR:
reg[42:0] LFSR_varLFSR;
reg outbitLFSR;
always @(posedge clk)

   begin

   if ( rst )
      begin
        LFSR_reg  = (1);
      end
   else
      begin

         if (ena) begin

         LFSR_varLFSR =LFSR_reg ;

         outbitLFSR =LFSR_varLFSR [42];
         LFSR_varLFSR [42]=LFSR_varLFSR [41];
         LFSR_varLFSR [41]=LFSR_varLFSR [40]^outbitLFSR ;
         LFSR_varLFSR [40]=LFSR_varLFSR [39];
         LFSR_varLFSR [39]=LFSR_varLFSR [38];
         LFSR_varLFSR [38]=LFSR_varLFSR [37];
         LFSR_varLFSR [37]=LFSR_varLFSR [36];
         LFSR_varLFSR [36]=LFSR_varLFSR [35];
         LFSR_varLFSR [35]=LFSR_varLFSR [34];
         LFSR_varLFSR [34]=LFSR_varLFSR [33];
         LFSR_varLFSR [33]=LFSR_varLFSR [32];
         LFSR_varLFSR [32]=LFSR_varLFSR [31];
         LFSR_varLFSR [31]=LFSR_varLFSR [30];
         LFSR_varLFSR [30]=LFSR_varLFSR [29];
         LFSR_varLFSR [29]=LFSR_varLFSR [28];
         LFSR_varLFSR [28]=LFSR_varLFSR [27];
         LFSR_varLFSR [27]=LFSR_varLFSR [26];
         LFSR_varLFSR [26]=LFSR_varLFSR [25];
         LFSR_varLFSR [25]=LFSR_varLFSR [24];
         LFSR_varLFSR [24]=LFSR_varLFSR [23];
         LFSR_varLFSR [23]=LFSR_varLFSR [22];
         LFSR_varLFSR [22]=LFSR_varLFSR [21];
         LFSR_varLFSR [21]=LFSR_varLFSR [20];
         LFSR_varLFSR [20]=LFSR_varLFSR [19]^outbitLFSR ;
         LFSR_varLFSR [19]=LFSR_varLFSR [18];
         LFSR_varLFSR [18]=LFSR_varLFSR [17];
         LFSR_varLFSR [17]=LFSR_varLFSR [16];
         LFSR_varLFSR [16]=LFSR_varLFSR [15];
         LFSR_varLFSR [15]=LFSR_varLFSR [14];
         LFSR_varLFSR [14]=LFSR_varLFSR [13];
         LFSR_varLFSR [13]=LFSR_varLFSR [12];
         LFSR_varLFSR [12]=LFSR_varLFSR [11];
         LFSR_varLFSR [11]=LFSR_varLFSR [10];
         LFSR_varLFSR [10]=LFSR_varLFSR [9];
         LFSR_varLFSR [9]=LFSR_varLFSR [8];
         LFSR_varLFSR [8]=LFSR_varLFSR [7];
         LFSR_varLFSR [7]=LFSR_varLFSR [6];
         LFSR_varLFSR [6]=LFSR_varLFSR [5];
         LFSR_varLFSR [5]=LFSR_varLFSR [4];
         LFSR_varLFSR [4]=LFSR_varLFSR [3];
         LFSR_varLFSR [3]=LFSR_varLFSR [2];
         LFSR_varLFSR [2]=LFSR_varLFSR [1];
         LFSR_varLFSR [1]=LFSR_varLFSR [0]^outbitLFSR ;
         LFSR_varLFSR [0]=LFSR_varLFSR [42];

         LFSR_reg  = (LFSR_varLFSR );

         end
      end
   end

//combinate:
always @(posedge clk)
   begin

   if ( rst )
      begin
        number_o  = (0);
      end
   else

      if (ena) begin
        number_o  = (LFSR_reg [31:0]^CASR_reg[31:0]);
      end
   end

endmodule

I piped this thing through HD video at different resolutions and signal gains.  Unlike the Xilinx LFSR code examples in my .pdf links 2 posts above, which at some video sizes made a pattern go through the video like an analog TV broadcast with a weak interfering radio broadcast over the channel, or adjacent still image, this random number generator was a pure non-patterned perfect grain.
« Last Edit: June 26, 2017, 10:43:04 am by BrianHG »
 

Offline Moshly

  • Regular Contributor
  • *
  • Posts: 139
  • Country: au
  • What's wrong with this thing
Re: Building musical synthesizers and keyboards
« Reply #51 on: June 26, 2017, 10:42:29 am »
Hi, Just thought I'd add this bit from an interview with Bob Yannes (Designer of the C64's SID chip)
Highlighted part about noise waveform generation. Specifically -> The noise generator is implemented as a 23-bit-length Fibonacci LFSR (Feedback polynomial: x^22+x^17+1).

Quote
ANDREAS : Can you give us a short overview of the SIDs internal architecture?

BOB YANNES : It's pretty brute-force, I didn't have time to be elegant. Each "voice" consisted of an Oscillator, a Waveform Generator, a Waveform Selector, a Waveform D/A converter, a Multiplying D/A converter for amplitude control and an Envelope Generator for modulation. The analog output of each voice could be sent through a Multimode Analog Filter or bypass the filter and a final Multiplying D/A converter provided overall manual volume control.

As I recall, the Oscillator is a 24-bit phase-accumulating design of which the lower 16-bits are programmable for pitch control. The output of the accumulator goes directly to a D/A converter through a waveform selector. Normally, the output of a phase-accumulating oscillator would be used as an address into memory which contained a wavetable, but SID had to be entirely self-contained and there was no room at all for a wavetable on the chip.

The Sawtooth waveform was created by sending the upper 12-bits of the accumulator to the 12-bit Waveform D/A.

The Triangle waveform was created by using the MSB of the accumulator to invert the remaining upper 11 accumulator bits using EXOR gates. These 11 bits were then left-shifted (throwing away the MSB) and sent to the Waveform D/A (so the resolution of the triangle waveform was half that of the sawtooth, but the amplitude and frequency were the same).

The Pulse waveform was created by sending the upper 12-bits of the accumulator to a 12-bit digital comparator. The output of the comparator was either a one or a zero. This single output was then sent to all 12 bits of the Waveform D/A.

The Noise waveform was created using a 23-bit pseudo-random sequence generator (i.e., a shift register with specific outputs fed back to the input through combinatorial logic).The shift register was clocked by one of the intermediate bits of the accumulator to keep the frequency content of the noise waveform relatively the same as the pitched waveforms. The upper 12-bits of the shift register were sent to the Waveform D/A.

Since all of the waveforms were just digital bits, the Waveform Selector consisted of multiplexers that selected which waveform bits would be sent to the Waveform D/A. The multiplexers were single transistors and did not provide a "lock-out", allowing combinations of the waveforms to be selected. The combination was actually a logical ANDing of the bits of each waveform, which produced unpredictable results, so I didn't encourage this, especially since it could lock up the pseudo-random sequence generator by filling it with zeroes.

The output of the Waveform D/A (which was an analog voltage at this point) was fed into the reference input of an 8-bit multiplying D/A, creating a DCA (digitally-controlled-amplifier). The digital control word which modulated the amplitude of the waveform came from the Envelope Generator.

The Envelope Generator was simply an 8-bit up/down counter which, when triggered by the Gate bit, counted from 0 to 255 at the Attack rate, from 255 down to the programmed Sustain value at the Decay rate, remained at the Sustain value until the Gate bit was cleared then counted down from the Sustain value to 0 at the Release rate.

A programmable frequency divider was used to set the various rates (unfortunately I don't remember how many bits the divider was, either 12 or 16 bits). A small look-up table translated the 16 register-programmable values to the appropriate number to load into the frequency divider. Depending on what state the Envelope Generator was in (i.e. ADS or R), the appropriate register would be selected and that number would be translated and loaded into the divider. Obviously it would have been better to have individual bit control of the divider which would have provided great resolution for each rate, however I did not have enough silicon area for a lot of register bits. Using this approach, I was able to cram a wide range of rates into 4 bits, allowing the ADSR to be defined in two bytes instead of eight. The actual numbers in the look-up table were arrived at subjectively by setting up typical patches on a Sequential Circuits Pro-1 and measuring the envelope times by ear (which is why the available rates seem strange)!

In order to more closely model the exponential decay of sounds, another look-up table on the output of the Envelope Generator would sequentially divide the clock to the Envelope Generator by two at specific counts in the Decay and Release cycles. This created a piece-wise linear approximation of an exponential. I was particularly happy how well this worked considering the simplicity of the circuitry. The Attack, however, was linear, but this sounded fine.

A digital comparator was used for the Sustain function. The upper four bits of the Up/Down counter were compared to the programmed Sustain value and would stop the clock to the Envelope Generator when the counter counted down to the Sustain value. This created 16 linearly spaced sustain levels without having to go through a look-up table translation between the 4-bit register value and the 8-bit Envelope Generator output. It also meant that sustain levels were adjustable in steps of 16. Again, more register bits would have provided higher resolution.

When the Gate bit was cleared, the clock would again be enabled, allowing the counter to count down to zero. Like an analog envelope generator, the SID Envelope Generator would track the Sustain level if it was changed to a lower value during the Sustain portion of the envelope, however, it would not count UP if the Sustain level were set higher.

The 8-bit output of the Envelope Generator was then sent to the Multiplying D/A converter to modulate the amplitude of the selected Oscillator Waveform (to be technically accurate, actually the waveform was modulating the output of the Envelope Generator, but the result is the same).

Hard Sync was accomplished by clearing the accumulator of an Oscillator based on the accumulator MSB of the previous oscillator.

Ring Modulation was accomplished by substituting the accumulator MSB of an oscillator in the EXOR function of the triangle waveform generator with the accumulator MSB of the previous oscillator. That is why the triangle waveform must be selected to use Ring Modulation.

The Filter was a classic multi-mode (state variable) VCF design. There was no way to create a variable transconductance amplifier in our NMOS process, so I simply used FETs as voltage-controlled resistors to control the cutoff frequency. An 11-bit D/A converter generates the control voltage for the FETs (it's actually a 12-bit D/A, but the LSB had no audible affect so I disconnected it!).

Filter resonance was controlled by a 4-bit weighted resistor ladder. Each bit would turn on one of the weighted resistors and allow a portion of the output to feed back to the input. The state-variable design provided simultaneous low-pass, band-pass and high-pass outputs. Analog switches selected which combination of outputs were sent to the final amplifier (a notch filter was created by enabling both the high and low-pass outputs simultaneously).

The filter is the worst part of SID because I could not create high-gain op-amps in NMOS, which were essential to a resonant filter. In addition, the resistance of the FETs varied considerably with processing, so different lots of SID chips had different cutoff frequency characteristics. I knew it wouldn't work very well, but it was better than nothing and I didn't have time to make it better.

Analog switches were also used to either route an Oscillator output through or around the filter to the final amplifier. The final amp was a 4-bit multiplying D/A converter which allowed the volume of the output signal to be controlled. By stopping an Oscillator, it was possible to apply a DC voltage to this D/A. Audio could then be created by having the microprocessor write the Final Volume register in real-time. Game programs often used this method to synthesize speech or play "sampled" sounds. An external audio input could also be mixed in at the final amp or processed through the filter.

The Modulation registers were probably never used since they could easily be simulated in software without having to give up a voice. For novice programmers they provided a way to create vibrato or filter sweeps without having to write much code (just read the value from the modulation register and write it back to the frequency register). These registers just give microprocessor access to the upper 8 bits of the instantaneous value of the waveform and envelope of Voice 3. Since you probably wouldn't want to hear the modulation source in the audio output, an analog switch was provided to turn off the audio output of Voice 3.

ANDREAS : Any other interesting tidbits or anecdotes?

BOB YANNES : The funniest thing I remember was getting in a whole bunch of C-64 video games which had been written in Japan. The Japanese are so obsessed with technical specifications that they had written their code according to a SID spec. sheet (which I had written before SID prototypes even existed). Needless to say, the specs were not accurate. Rather than correct the obvious errors in their code, they produced games with out of tune sounds and filter settings that produced only quiet, muffled sound at the output. As far as they were concerned, it didn't matter that their code sounded all wrong, they had written their code correctly according to the spec. and that was all that mattered!
 

Offline GK

  • Super Contributor
  • ***
  • Posts: 2607
  • Country: au
Re: Building musical synthesizers and keyboards
« Reply #52 on: June 26, 2017, 01:01:19 pm »
@GK, would you accept that in this document: https://web.archive.org/web/20161007061934/http://courses.cse.tamu.edu/csce680/walker/lfsr_table.pdf
Page 1, table 1, the 24 bit LFSR-4 is the 24bit LFSR random number generator you are talking about?
Or this one: http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
Page 5, table 3, the 24 bit LFSR-4 is the 24bit LFSR random number generator you are talking about?
(The 2 differ slightly by choosing 2 different bits to xor with the output, but they should be close)

If so, give me this weekend and I will plot the monochrome results on a 2d B&W image and going a step further I'll plot another version using bits 24 & 23 to create 4 shades of grey to see if we have any visual pattern.  If the results are a perfect snow, then yes, there would be no coincidental mixing artifacts with this noise generator mixed with other tones in a music synthesizer.

If there are any visible patterns, these patterns will, when mixed with some tones or notes in a music synthesize create an audible artifact.
Can we agree on this much?

(I like these challenges and will admit defeat if I cant find any patterns...)


Mate, I don't have the time or the energy to get into this in depth right now or follow all of your links, but I don't think I need to. Surely tens if not hundreds of thousands of laboratory-grade maximal-count-LFSR-based noise sources have been professional and semi-professionally manufactured since the 50s or the 60s when I believe HP popularized the technique.

I've got a one here based on a PIC MCU that covers the audio frequency spectrum and the pseudo-random bit sequence generated is sufficient for the output spectrum to look completely flat and stable down towards DC as far as any available spectrum analyzer can see. And it sounds exactly so when I plug it into an amplifier and listen to it. A LFSR that is wholly adequate for audio-spectrum noise generation is a trivial thing to code in even the most crufty MCU in my experience.

No offense intended, but I think that persisting to imply that such a well established technique (in both theory and practice) for generating noise that is for all practical purposes sufficiently random for a plethora of sensitive test and measurement purposes is otherwise intrinsically deficient for audio signal generation might be venturing into audiophool territory.
Bzzzzt. No longer care, over this forum shit.........ZZzzzzzzzzzzzzzzz
 

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16562
  • Country: 00
Re: Building musical synthesizers and keyboards
« Reply #53 on: June 26, 2017, 01:24:52 pm »
No offense intended, but I think that persisting to imply that such a well established technique (in both theory and practice) for generating noise that is for all practical purposes sufficiently random for a plethora of sensitive test and measurement purposes is otherwise intrinsically deficient for audio signal generation might be venturing into audiophool territory.

Yes, this has got slightly derailed. The original problem was that some non-analog synthesizers use a small lookup table to generate noise (because internally that's how they generate all their periodic waveforms).
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: Building musical synthesizers and keyboards
« Reply #54 on: June 26, 2017, 02:00:14 pm »
With the super analog sounding 96bit noise generator plus the extra analog algorithm been suggested here would cost me at least 1 voice polyphony.

I dont know if some manufacturers has all that fancy stuff in there, i,m not going to waste my DSPIC on some noise generator,
i have to get started with 32bit chips + external DAC maybe that solves things a bit with more power, you cannot fake analog noise, all transistors sound different.

Are you really making digital synthesizers sounding analog with this ?, lets hear it.
aliexpress parachute
 

Offline dave_j_fan

  • Regular Contributor
  • *
  • Posts: 169
  • Country: in
Re: Building musical synthesizers and keyboards
« Reply #55 on: June 26, 2017, 04:12:03 pm »
see midi versions :)

coin touch type
 
The following users thanked this post: MK14, BrianHG

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16562
  • Country: 00
Re: Building musical synthesizers and keyboards
« Reply #56 on: June 27, 2017, 11:15:00 am »
With the super analog sounding 96bit noise generator plus the extra analog algorithm been suggested here would cost me at least 1 voice polyphony.

I dont know if some manufacturers has all that fancy stuff in there, i,m not going to waste my DSPIC on some noise generator,

It's overkill, yes, but your claim was that: "If a analog noise-generator is used for random values in the chip, yes, then you can fool me with digital, else it sounds predictable."

I'm sure there's a simpler/faster RNG that will be good enough for white noise. It will be slightly CPU dependent though, what chip are you using?

i have to get started with 32bit chips + external DAC maybe that solves things a bit with more power, you cannot fake analog noise, all transistors sound different.

More processing power is always good. Or ... use parallel chips if you want to stick with what you know. Parallel chips can scale to any amount of polyphony.
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: Building musical synthesizers and keyboards
« Reply #57 on: June 27, 2017, 12:05:02 pm »
I'm sure there's a simpler/faster RNG that will be good enough for white noise. It will be slightly CPU dependent though, what chip are you using?

DSPIC33FJ128GP802

More processing power is always good. Or ... use parallel chips if you want to stick with what you know. Parallel chips can scale to any amount of polyphony.

Jes i want that, it also sounds better.
Small beginner problem : i still need to begin learning how SPI communication work to let the chips talk to eachother.
Once i have the SPI i will be like a mad scientist.
aliexpress parachute
 

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16562
  • Country: 00
Re: Building musical synthesizers and keyboards
« Reply #58 on: June 29, 2017, 11:44:24 am »
I'm sure there's a simpler/faster RNG that will be good enough for white noise. It will be slightly CPU dependent though, what chip are you using?

DSPIC33FJ128GP802

That chip has plenty of RAM (16kb) so I'd think about using RC4 stream cipher for random numbers. It needs 256 bytes of workspace RAM but has cryptographically strong output and only needs a few clock cycles per byte.

https://en.wikipedia.org/wiki/RC4

If you're producing 16 bit samples then try using only 8 bits of random. This sounds counter-intuitive but less bits actually equates to "more noise!" in the signal processing world, which is exactly what you want.  :popcorn:

(eg. 'tape hiss' is just 'not enough bits' if you analyze it mathematically).

This video shows it beautifully:


If you insist on the full 16 bits then simply combine the byte output of RC4 with the byte which is 128 bytes away from it in the RAM buffer or something like that.
« Last Edit: June 29, 2017, 12:19:13 pm by Fungus »
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: Building musical synthesizers and keyboards
« Reply #59 on: June 29, 2017, 02:27:23 pm »
Hi, thanks, you have any C code for one frame ?
aliexpress parachute
 

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16562
  • Country: 00
Re: Building musical synthesizers and keyboards
« Reply #60 on: June 29, 2017, 03:10:05 pm »
Hi, thanks, you have any C code for one frame ?

Code: [Select]
void swap(int a, int b)
{
unsigned char temp= s[i];
s[i]=s[j];
s[j]=temp;
}

unsigned char getbyte(void)
{
i=(i+1)%256;
j=(j+s[i])%256;
swap(i, j);
int index=(s[i]+s[j])%256;
return s[index];
}

« Last Edit: June 29, 2017, 03:13:10 pm by Fungus »
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: Building musical synthesizers and keyboards
« Reply #61 on: June 29, 2017, 03:36:57 pm »
You serious ?, i,m not gonna use any modulo, what 3 modulo`s.
aliexpress parachute
 

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16562
  • Country: 00
Re: Building musical synthesizers and keyboards
« Reply #62 on: June 29, 2017, 03:46:51 pm »
You serious ?, i,m not gonna use any modulo, what 3 modulo`s.

??? What do they teach kids in school these days?

Modulo 256 is easy. I bet even your C compiler knows how to optimize it.

Hint: If you declare i, j and 'index' as unsigned 8-bit variables then you can leave out the all modulus operations, it will work exactly the same.
« Last Edit: June 29, 2017, 03:53:58 pm by Fungus »
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: Building musical synthesizers and keyboards
« Reply #63 on: June 29, 2017, 04:12:42 pm »
Ok thanks, will the output still be full 16 bit ?
aliexpress parachute
 

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16562
  • Country: 00
Re: Building musical synthesizers and keyboards
« Reply #64 on: June 29, 2017, 04:41:45 pm »
Modulo 256 is easy. I bet even your C compiler knows how to optimize it.

Hint: If you declare i, j and 'index' as unsigned 8-bit variables then you can leave out the all modulus operations, it will work exactly the same.

As a test I compiled this code for Arduino (I don't have PIC installed):

Code: [Select]
byte i=0,j=0;
byte s[256];
void swap(byte a, byte b)
{
byte temp= s[a];
s[a]=s[a];
s[a]=temp;
}

byte getbyte(void)
{
i=(i+1)%256;
j=(j+s[i])%256;
swap(i, j);
byte index=(s[i]+s[j])%256;
return s[index];
}

Note that there's a huge bug in that code that I randomly pulled off the 'net. The "swap" function has parameters called 'a' and 'b' but uses 'i' and 'j' in the code(!)

The disassembled output from that is:
Code: [Select]
000000c0 <_Z7getbytev>:
  c0: 80 91 11 02 lds r24, 0x0211
  c4: 8f 5f        subi r24, 0xFF ; 255
  c6: 90 e0        ldi r25, 0x00 ; 0
  c8: 80 93 11 02 sts 0x0211, r24
  cc: fc 01        movw r30, r24
  ce: e0 5f        subi r30, 0xF0 ; 240
  d0: fe 4f        sbci r31, 0xFE ; 254
  d2: 80 81        ld r24, Z
  d4: e0 91 10 02 lds r30, 0x0210
  d8: e8 0f        add r30, r24
  da: e0 93 10 02 sts 0x0210, r30
  de: f0 e0        ldi r31, 0x00 ; 0
  e0: e0 5f        subi r30, 0xF0 ; 240
  e2: fe 4f        sbci r31, 0xFE ; 254
  e4: e0 81        ld r30, Z
  e6: e8 0f        add r30, r24
  e8: f0 e0        ldi r31, 0x00 ; 0
  ea: e0 5f        subi r30, 0xF0 ; 240
  ec: fe 4f        sbci r31, 0xFE ; 254
  ee: 80 81        ld r24, Z
  f0: 08 95        ret

No modulus operations in sight, the compiler simply ignores them! (as predicted)

Edit: Out of interest I didn't initialize the state table the first time I tried it and the compiler optimized away the entire thing on the grounds that the table was filled with zeros and therefore unnecessary.

ie. The table vanished from RAM and the getByte() function compiled to "i=i+1; return 0;"

What exactly are they feeding those compilers these days?
« Last Edit: June 29, 2017, 05:03:06 pm by Fungus »
 

Online Fungus

  • Super Contributor
  • ***
  • Posts: 16562
  • Country: 00
Re: Building musical synthesizers and keyboards
« Reply #65 on: June 29, 2017, 04:43:10 pm »
Ok thanks, will the output still be full 16 bit ?

Code: [Select]
unsigned char getbyte(void)
{
 ...
}

It was never 16 bits.
 

Offline GK

  • Super Contributor
  • ***
  • Posts: 2607
  • Country: au
Re: Building musical synthesizers and keyboards
« Reply #66 on: June 30, 2017, 02:50:42 pm »
This discussion in the context of synth noise generation isn't making a lot of sense  :-//

A maximal-count LFSR (linear feedback shift register) will repeat its bit sequence every (2^n)/2 clock cycles, where n is the number of register bits.

So a 24-bit LFSR clocked at 44kHz will repeat its bit sequence every 190s. Nobody has the auditory memory to pick up on that.



Correcting myself here, that's every 2n-1 clock cycles. Don't know where I remembered (2^n)/2 from, maybe from some different kind of feedback arrangement, or perhaps miss-remembered.
So the 24-bit counter would repeat every 380s rather than 190s. Incidentally a 20, 21, 22, 23, 25 or 28-bit maximal-count LFSR can be made with just two feedback taps (just a single xor). 

Here is a quick experiment it SPICE. It a 16-bit maximal-count (requiring 4 taps) LFSR clocked at 40kHz. a 10kHz 3-pole LPF filters the pseudo random bit stream and defines the noise bandwidth. I've used the .wave directive the record the output as a 16-bit 44.1kHz WAV file. The bit sequence repeats every (1/40k)*((2^16)-1) = 1.64s
I recorded 5s worth. The LTSPICE *.ASC file and the WAV audio file are attached. Have a listen: https://www.eevblog.com/forum/projects/building-musical-synthesizers-and-keyboards/?action=dlattach;attach=328141



For a good read on the power spectrum of pseudo random bit sequences see here: http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1967-09.pdf


« Last Edit: June 30, 2017, 02:53:38 pm by GK »
Bzzzzt. No longer care, over this forum shit.........ZZzzzzzzzzzzzzzzz
 
The following users thanked this post: MK14

Offline homeless_peep

  • Contributor
  • Posts: 21
  • Country: gr
Re: Building musical synthesizers and keyboards
« Reply #67 on: August 04, 2017, 10:33:26 am »
Sound generation (VCOs, noise, etc) and sound processing (filters, phasers,overdrives...) are generally good candidates for analog implementations. People will argue that DSP is more accurate, which is true, but the little nuances of analog circuits (pitch instability, possibly noise or intermodulations and so on) do make a difference and produce a character. Filters and distortions in particular sound absolutely shitty, empty and uninteresting on digital synths.
VCOs are a very hard thing to nail. Exponential VCOs (1V/oct standard) are VERY depended on temperatures, which will be your greatest problem. Tempco resistors are a solution, but thermal oven compensation is more straightforward and works great (and maybe, better?).
I suggest investigating the sawtooth core topology, because of it's low price and easy to find components. Triangle cores can be a bitch to perfect and are certainly more expensive.
Filters come in all forms, prices, shapes, just google some and use a verified design. The moog cascade filter is an absolute classic in synths and it's not much of a hassle at all.
VCAs can be designed in a number of ways, one of the most economical is to look at the LM13700 (or CA3080) applications.
Distortions can be as simple as a diode clipper/fuzzer, but you can get more fancy if you care that much.
Control signals (sequencers, LFOs, envelopes) can all be made with analog/discrete components, but since you have digital skills, just make them with a processor. You will have advanced functions like syncing to external tempo/clock, phase difference between LFOs, sequence save/recall etc. It is also considerably cheaper to do it that way.
Various flavors of noise are used, a simple "white" one can be made using a couple of transistors and resistors.
YUsynth has a ton of stuff and projects available on his website, along with schematics, boards and short explainations. There you can also find the full schematics of the microbrute and mini brute synthesizers. Both are commercial, low cost synths that combine analog and digital methods (analog sound-digital control. kind of.) and can teach you more about synthesizer systems architecture.
Knowing the LM13700 is an absolute must in this field, as well as differential pair applications in general. Have a SPICE simulator by your side at all times- it will help you a lot.
 
The following users thanked this post: FlyingHacker


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf