PDA

View Full Version : Propellamin - Need help from those familiar with music + audio programming



watermoccasin
07-22-2009, 11:05 PM
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[counter+1] := Samples[Counter]
Samples[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[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!

T Chap
07-23-2009, 12:57 AM
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 Fwed
07-23-2009, 12:58 AM
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 Loop
07-23-2009, 04:25 AM
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.

http://www.youtube.com/watch?v=9Jmz5LirTjs

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%2cProductName

Post Edited (Clock Loop) : 7/22/2009 9:38:38 PM GMT

Ariba
07-23-2009, 05:26 AM
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[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[DAC] := 1 'Set up DAC
ctra := %00110 << 26 + DAC 'counter A in DUTY mode
frqa := NULL
repeat 'DDS loop:
phase += long[pFreq] 'add freq to phase
' frqa := phase>>16 * long[pVolume] + NULL 'mult saw with volume
frqa := (||phase-NULL)>>16 * long[pVolume] + NULL 'convert to triangle and mult with volume
' frqa := (phase&NULL>>1)>>16 * long[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

Rayman
07-23-2009, 02:42 PM
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

Rayman
07-23-2009, 02:44 PM
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