Shop OBEX P1 Docs P2 Docs Learn Events
Propellamin - Need help from those familiar with music + audio programming — Parallax Forums

Propellamin - Need help from those familiar with music + audio programming

watermoccasinwatermoccasin Posts: 1
edited 2009-07-23 07:44 in Propeller 1
Hi, I'm new to the forums and just started working with the propeller, and have a few questions for my first project.
First a little about the project . . .
Currently dubbed the propellamin, the device will be a propeller-controlled theremin-like instrument, using sonar (PING) rather than radio-freqency as input for frequency and volume.

I have many ideas that will be able to take advantage of a digitized version of this instrument, and the first is programming a specific pitch to a range, allowing the musician to easily play in any key. With the help of forum member Casslan, I have tied an average (AVG) of ping readings to an existing pitch-generator program with a table linking range to pitch, but I cannot seem to play frequencies that are not a whole number. I am able to get very close to an actual scale, but especially at lower frequencies this is very limiting. Below is the code I currently have for playing this instrument in C Maj.

VAR

  long  range

  long  Samples, AVG, SUM
  byte  counter
  long  Frequency
  byte numofsamples
    
OBJ

  Term : "FullDuplexSerialPlus"
  ping : "ping"
  Synth : "Synth"

  
PUB Start

  Term.StartPST(115200)
  
  numofsamples:= 5

  repeat
      Term.CursorHome
      repeat counter from 0 to numofsamples             ' Repeat Forever 
          Samples[noparse][[/noparse]counter+1] := Samples[noparse][[/noparse]Counter]
      Samples[noparse][[/noparse]0] := ping.Ticks(PING_Pin)                                                                                                                                   ' Position Cursor                                                            ' Print Fractional Part
      'waitcnt(clkfreq / 10 + cnt)                      ' Pause 1/10 Second
      SUM:=0
      repeat counter from 0 to numofsamples
        SUM := SUM + Samples[noparse][[/noparse]counter]
      AVG := (SUM/numofsamples)
      AVG := AVG -100
      case AVG
        0..100: Frequency := 131    'C3
        101..200: Frequency := 147 'D3
        201..300: Frequency := 165 'E3
        301..400: Frequency := 175 'F3
        401..500: Frequency := 196  'G3
        501..600: Frequency := 220  'A3
        601..700: Frequency := 245 'B3
        701..800: Frequency := 262 'C4
        801..900: Frequency := 294 'D4
        901..1000: Frequency := 330 'E4
        1001..1100: Frequency := 349 'F4
        1101..1200: Frequency := 392 'G4
        1201..1300: Frequency := 440 'A4
        1301..1400: Frequency := 494 'B4
        1401..1500: Frequency := 523 'C5
      Synth.Synth("A", 10, Frequency)
      Term.Str(String("AVG-100: "))
      Term.dec(AVG)
      Term.str(string("      ")) ' Print Inches
      Term.CarriageReturn
      Term.Str(String("FRE: "))
      Term.dec(Frequency)
      Term.str(string("      ")) ' Print Inches
      Term.CarriageReturn



Below is how the table should read:
        0..100: Frequency := 130.81    'C3
        101..200: Frequency := 146.83 'D3
        201..300: Frequency := 164.81 'E3
        301..400: Frequency := 174.61 'F3
        401..500: Frequency := 196  'G3
        501..600: Frequency := 220  'A3
        601..700: Frequency := 246.94 'B3
        701..800: Frequency := 261.63 'C4
        801..900: Frequency := 293.66 'D4
        901..1000: Frequency := 329.63 'E4
        1001..1100: Frequency := 349.23 'F4
        1101..1200: Frequency := 392 'G4
        1201..1300: Frequency := 440 'A4
        1301..1400: Frequency := 493.88 'B4
        1401..1500: Frequency := 523.25 'C5




My first questions for the forum are these:
**How can I get the pitch generator to generate a pitch that is not a whole number?

Does anyone have an idea for the code that would allow the pitch to slide smoothly from one specific note to the next while playing?

Is there a way to control the volume for the pitch generator with programming? If not I plan on using a digital potentiometer to control the signal coming from the generator.

Thanks for your help. I will try to keep progress updated, and if anyone has any other ideas for this project I am happy to hear any advice!

Comments

  • T ChapT Chap Posts: 4,223
    edited 2009-07-22 17:57
    I didn't look at the code but here are some thoughts to get smooth glide from note to note:

    You may want to look at the counters as a method to generate high res frequencies. Then take those hi frequencies and divide them down to a usable frequency for the real world. This way you can move from note to note (gliss) in large numbers (up to 32 bits, but the output is divided down to notes in a usable range. So for every counter pulse, you output a counter value divided by X (maybe even 10, 100, or 1000).

    Someone else may know a way to divide the counter output, but two ideas that come to mind:

    1. Output a counter at frequency X on a pin that represents a hi res note value (i.e. A440 would be counter freq of 440,000, send back to an input, divide the input by some fixed value to produce usable musical frequencies and output the result.

    or

    2. Operate a counter at a frequency, divide the counter with some means internally. My counter experience is limited but there is an app note on the Prop info areathat is very informative.

    Either method should allow sliding between notes once you get it sorted out. The hi res frequency can be easily added to or subtracted from to.

    Using low res (real world frequencies) as you are dong in your code will not allow for any smooth transitions between whole or half notes.

    The Ping input could be the controlling factor for the counters frequency, and you could change the counters output in real time with the Ping. You could also quantize the output with case statements.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-07-22 17:58
    I don't know how exactly you get the decimals for the frequency, but I know it is possible (it's just a matter of math) since the frequency value is 32-bit.
    As for the the smooth transition, it would be a math function... you could try this: Frequency := -56036 / AVG + 560
    I think I did that right.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!
  • Clock LoopClock Loop Posts: 2,069
    edited 2009-07-22 21:25
    I have made a musical device using the propeller, and my suggestion to you would be to use what I use.

    HSS


    I will be releasing my code for my musical device, along with the schematics, and with it you can eaisly attach a theremin.

    And it would be very easy to program a theremin input on it and have it represent one of many sound waveform modifiers.

    I do it with my prop fx/sequencer.



    I don't have a theremin, or its schematics, but im sure if I looked into it, it would be easy to make it be a frequency modifier.

    The same could be done with a 1-axis accelerometer. 3 axis would get fun.

    I have the one below and plan to program it to do whatever i want.

    http://www.parallax.com/Store/Sensors/AccelerationTilt/tabid/172/CategoryID/47/List/0/Level/a/ProductID/97/Default.aspx?SortField=ProductName,ProductName

    Post Edited (Clock Loop) : 7/22/2009 9:38:38 PM GMT
  • AribaAriba Posts: 2,690
    edited 2009-07-22 22:26
    The synth object is not ment for music synthesis, it just helps to set a counter to a desired frequency.
    What you need is a DDS Tone Generator (DDS=Direct Digital Synthesis) with a PWM modulated output to control
    the volume.
    There are some objects for the Hydra (i.e. the HSS that ClockLoop suggested). They normally need to be coded
    in Assembly, but for a simple Test (and to show the concept) it's also possible within Spin:
    {{ DDS Synth example }}
    
    CON  _clkmode      = xtal1 + pll16x                                    
         _xinfreq      = 5_000_000
    
         NULL = $8000_0000
         DAC  = 10           '<-- Audio Out Pin
    
    VAR  long  freq         '~10_000_000 .. 200_000_000
         long  volume       '0 .. 32767
         long  UpDown
         long  stack[noparse][[/noparse]20]
    
    PUB Main
      cognew(DDS_Gen(@freq,@volume),@stack)        'Start Synth Cog
    
      repeat                                       'Demo loop:
        repeat freq from 10_000_000 to 150_000_000 step 200    'freq sweep
          if UpDown==1                                         'volume up/down
            volume += 5
            if volume > 32000
              UpDown := 0
          else
            volume -= 1
            if volume < 50
              UpDown := 1
      
       
    PUB DDS_Gen(pFreq, pVolume) | phase            'Synth Cog, produces a triangle wave
      dira[noparse][[/noparse]DAC] := 1                               'Set up DAC
      ctra := %00110 << 26 + DAC                   'counter A in DUTY mode
      frqa := NULL
      repeat                                       'DDS loop:
        phase += long[noparse][[/noparse]pFreq]                               'add freq to phase
    '    frqa := phase>>16 * long[noparse][[/noparse]pVolume] + NULL           'mult saw with volume
        frqa := (||phase-NULL)>>16 * long[noparse][[/noparse]pVolume] + NULL  'convert to triangle and mult with volume
    '    frqa := (phase&NULL>>1)>>16 * long[noparse][[/noparse]pVolume] + NULL 'convert to square and mult with volume
    
    


    This starts a new cog for generating a frequency with volume control. You can control this parameters
    from the Main loop with the 2 variables: freq and volume (for range see comments in VAR section).

    There are 3 waveforms in the example which you can change by uncommenting 1 of the 3 "frqa := ..." lines.

    For your Theremin you can have 2 Ping sensors.
    The first ping controls the frequency:
    freq := AVG1 * 100_000
    The second controls the volume:
    volume := AVG2 * 2000


    Andy
  • RaymanRayman Posts: 14,844
    edited 2009-07-23 07:42
    Here's a tone generator that makes sine waves...
    The frequency is spec'd as integer Hertz, but you could probably modify it to work in hundredths of Hertz...

    (I.e., Instead of giving it 440 for 440 Hz, just give it 44000 and then modify the code as required...)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    My Prop Info&Apps: ·http://www.rayslogic.com/propeller/propeller.htm
  • RaymanRayman Posts: 14,844
    edited 2009-07-23 07:44
    BTW: You just gave me an idea to use the 3-axis accelerometer on my PSM to do the same kind of thing... Maybe use x-axis tilt for frequency and y-axis for volume...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    My Prop Info&Apps: ·http://www.rayslogic.com/propeller/propeller.htm
Sign In or Register to comment.