<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: Forms of digital audio synthesis</title>
		<link>http://forums.leaflabs.com/topic.php?id=10329</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:18:07 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=10329" rel="self" type="application/rss+xml" />

		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22948</link>
			<pubDate>Fri, 15 Mar 2013 09:31:16 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22948@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Well finally! I got round to making a timer interrupt for millis, with the sample rate currently at 28022 (supposed to be 28125 but its no biggy!), using an incrementing variable which increments another variable called Milliseconds every 28 times the interrupt is ran, causes a time of about 999.9uS, pretty much on!&#60;/p&#62;
&#60;p&#62;Other than that, its fully working now, i've even incorporated using the integrated LiPo battery system.&#60;/p&#62;
&#60;p&#62;Thanks a lot as per!
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22940</link>
			<pubDate>Wed, 13 Mar 2013 18:47:13 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22940@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;pyrohaz - sorry, disabling systick will kill millis() and micros().&#60;br /&#62;
I had misunderstood, and thought you were driving everything with the 31,250Hz interrupt.&#60;/p&#62;
&#60;p&#62;Are you able to paste code here or at pastebin?&#60;br /&#62;
Are you able to extract the code, build it into a test harness, compile it on your PC, and have it print the values it comes up with? There may be an overflow or arithmetic error.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22937</link>
			<pubDate>Wed, 13 Mar 2013 15:20:38 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22937@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Right, I just disabled SerialUSB and that seemed to help it a tad, but whenever I disable systick, it seems to stop the program working all together! Is there anything else that could help? I do have a couple of switch statements in the interrupt (not massive though and no math either!)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22934</link>
			<pubDate>Wed, 13 Mar 2013 13:00:52 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22934@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;pyrohaz - it's well worth switching off interrupts just to see if that fixes the problem. Is it often enough to estimate its frequency?&#60;/p&#62;
&#60;p&#62;USB is switched off with &#60;code&#62;USBSerial::end()&#60;/code&#62;&#60;br /&#62;
Once this is done, the Maple will need to be put into permanent bootloader mode to upload code, or &#34;switch its power off and on again&#34; (IT Crowd:-)&#60;/p&#62;
&#60;p&#62;I think the systick timer can be disabled with:&#60;br /&#62;
&#60;code&#62;((uint32_t*)0xE000E010 ) = 0;&#60;/code&#62;&#60;br /&#62;
(ARM DDI0337E_cortex_m3_r1p1_trm.pdf section &#34;8.2.2 NVIC register descriptions&#34; page 8-8)&#60;/p&#62;
&#60;p&#62;An RC filter has a roll-off of 6dB/octave, so I assume it'll require quite a few octaves (frequency doubling) to remove conversion artefacts from the signal. It depends how much noise from conversion you can tolerate in the synthesised signal.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22933</link>
			<pubDate>Wed, 13 Mar 2013 12:26:51 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22933@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Right! Today I managed the linear interpolation method (I think this is the same as the DDS method tutorial I saw somewhere with my arduino).&#60;/p&#62;
&#60;p&#62;The only problem being that i'm using an interrupt every 31250Hz (calculated it should be that anyway, reading it is a few hz off) but I seem to be getting the odd click or &#34;discontinuity&#34; sound, its only quiet and not a biggy but it it noticeable with a sinewave array, my main loop is literally only calculating the tuning word for each sample, could this be due to other interrupts occuring? If so, how do I change my waveform writing interrupt to be of higher priority? The only other interrupt I really use is systick (using millis() in the loop, not important that millis is a correct value) once fully programmed, I can turn off USBSerial too.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22927</link>
			<pubDate>Tue, 12 Mar 2013 07:27:52 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22927@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Also in relation to the low pass filter, currently its just an RC low pass though making an active 2 pole filter wouldn't be too hard if that helps?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22868</link>
			<pubDate>Mon, 11 Mar 2013 18:05:12 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22868@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Yeh, while the the processor isn't producing sound, it isn't particularly busy, and even then it isnt! I thought of using a timed interrupt for writing the current sample to the PWM but as you say, the micros() section isn't particularly long and even when using SerialUSB, it doesn't seem to really affect the frequency which seems odd. I wrote a matlab program to tell me which array length will make for the most in tune set of samples which using standard musical notes, seems to be 411.&#60;/p&#62;
&#60;p&#62;Since I want to be able to produce waveforms other than just sine waves, how would a simple additive method suffice?&#60;/p&#62;
&#60;p&#62;In the sense that I just analyse the FFT spectrum of one cycle of waveform I want, then find the relative amplitude of the first 6 harmonics (obviously this will only work for waveforms where harmonics are related), then using:&#60;/p&#62;
&#60;p&#62;for(n=0; n&#38;lt;360; n++){&#60;br /&#62;
(a*sind(n) + a2*sind(2n) + ... +a6*sin(6n))/(sum of amplitudes)&#60;/p&#62;
&#60;p&#62;Where a = fundamental amplitude, a2 = second harmonic amplitude etc.&#60;/p&#62;
&#60;p&#62;Would this take too long to calculate? It would save a lot of space as I wouldn't need to store the arrays for every value, I would just need to store 6 different amplitudes for every wave that I wanted.&#60;/p&#62;
&#60;p&#62;Cheers,
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22848</link>
			<pubDate>Sun, 10 Mar 2013 20:12:05 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22848@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;pyrohaz - you wrote the processor isn't busy, so IMHO, don't make the maths more complex by interpolating values from an array; call &#60;code&#62;fsin(x)&#60;/code&#62; for the angle (fraction through the cycle) that is needed, before it is needed. The code should be simpler.&#60;/p&#62;
&#60;p&#62;&#60;code&#62;micros()&#60;/code&#62; is ordinary code, so it can be effected by an interrupt. The odds are very small as there is only a small amount of code to disrupt. However a very poor choice of sample rate (i.e. an integer multiple of an interrupt rate) could make that more common. &#60;/p&#62;
&#60;p&#62;Yes use a simple technique to get everything working, so start with micros(), and see how it performs. Likely good enough.&#60;/p&#62;
&#60;p&#62;The timers driving PWM channels have an interrupt service routine, and if it is a higher priority than all other interrupts, its timing will be very stable (i.e. it will be the stability of the 8MHz crystal oscillator, stability is usually quoted as 50ppm or better, with a constant delay on every interrupt to enter the interrupt service routine).&#60;/p&#62;
&#60;p&#62;Edit: I am interested in the low-pass filter being used on the output of the DAC. Is it quite sophisticated?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22844</link>
			<pubDate>Sun, 10 Mar 2013 16:12:07 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22844@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Hey guys, cheers for all the replies. I'll have to try this method cbrunschen, If I generate the number required to get the specific source, where do I then use that number? If I understand what you mean, is it kind of like getting the third sample, adding it to the fourth and dividing to get a value that is equal to 3.75? In respect to the original sample, it had no sample rate and is literally just an array of calculated sine values between zero and 256. Does this cause a problem?&#60;/p&#62;
&#60;p&#62;Thank you also for the reply gbulmer, all the processor is really doing otherwise is sending data through Serial 2 (every 300ms or so) and reading some inputs every 10ms, these reads were implemented using the if(current time - first time &#38;gt; sample time) method, when these inputs are read and when the data is sent over Serial 2 isn't very time dependent, as long as the values are around there. As you say, interrupts will affect the delay times but do they affect millis and micros?&#60;/p&#62;
&#60;p&#62;I could rewrite the above program to work through this same method in the sense of:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;TCurrent = micros();
if(TCurrent - TFirst &#38;gt; Notefreq){

  TFirst = TCurrent;

  pwmWrite(9, arrayu[arrayval]);

  arrayval = arrayval + 1;

  if(arrayval == 256){
    arrayval = 0;
    One_Cycle = 1;
  }
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;If micros() isn't affected by interrupts, I don't see any major problems in using this method, though I'm still to try interpolation!
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22840</link>
			<pubDate>Fri, 08 Mar 2013 16:48:55 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22840@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;pyrohaz - I assume you're using a much higher sample rate to make it easy to low-pass filter the signal?&#60;/p&#62;
&#60;p&#62;What are the characteristics of your low-pass filter? &#60;/p&#62;
&#60;p&#62;If the timer is clocked at 72MHz (or 36MHz) then an 11-bit (10-bit) count would give a sample frequency of 35.156kHz, which is about 89x (more than 6 octaves higher) the highest frequency you want to reconstruct (synthesise), which I guess is high enough for your electronics to filter easily? &#60;/p&#62;
&#60;p&#62;With a steeper filter, it'd be practical to use 13-bits, or even more, of precision, at an even lower sampling rate, and still reconstruct  (synthesise) the signal.&#60;/p&#62;
&#60;p&#62;(I mention 36MHz because the pwm signal can be 'symmetric', which means the counter counts up and then down each cycle, and hence can only reach 36MHz).&#60;/p&#62;
&#60;p&#62;You haven't said what else the processor is doing, but if there is plenty of CPU time available, maybe calculate the floating point value for sin(x) on the fly?&#60;br /&#62;
I've never run the benchmark, but I'd expect an STM32F1 to be able to calculate sin(x) in a few microseconds or faster.&#60;/p&#62;
&#60;p&#62;Don't use busy-delays, like delayMicroseconds. Use timers. The delayMicroseconds function is actually looping code crafted to last a specific time. However, if there are interrupts triggered during delayMicroseconds, is takes longer. If the USB interrupt is running, and the timer interrupt is running, the delay will stretch and be inconsistent ('jitter').&#60;/p&#62;
&#60;p&#62;AFAIK, the time to calculate sin(x) isn't constant, and it's a good idea to keep interrupt service routines short too, so I'd probably generate the sin(x) values in loop(), and write them into a buffer. Then the interrupt service routine could be quick, and more consistent in duration. It'd pick the next value out of the buffer, and write it into the timer channel.&#60;/p&#62;
&#60;p&#62;If you have other interrupts to service, which might cause the pwm-feeding interrupt service routines response time to 'jitter', and not be consistent, then you might use the Direct Memory Access (DMA) controller to write the PWM values with more consistent timing.&#60;/p&#62;
&#60;p&#62;(Full disclosure: I am not a member of LeafLabs staff.)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>cbrunschen on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22839</link>
			<pubDate>Fri, 08 Mar 2013 16:04:15 +0000</pubDate>
			<dc:creator>cbrunschen</dc:creator>
			<guid isPermaLink="false">22839@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;linear interpolation is a common technique that's not too difficult to implement, not very costly performance-wise and still gives much improved quality:&#60;/p&#62;
&#60;p&#62;Basically, you know the frequency at which your samples were collected (or generated); and you know the frequency that you're trying to play back. Divide one by the other and you get a factor: For each sample to be played back, you need to advance along your collected samples by this factor, which will likely be non-integral.&#60;/p&#62;
&#60;p&#62;For instance, if your original sample was at 200Hz, and you need to play back at 250Hz, your factor will be (250 / 200) = 5/4 = 1.25. So you would need to play back samples 0, 1.25, 2.5, 3.75, 5, etc.&#60;/p&#62;
&#60;p&#62;In order to actually generate sample at 'source time' 3.75, you'd split the this (let's call it 'tSrc') 3.75 into the integral and fractional part, '3' and '.75' respectively; call these 'n' and 'frac', respectively. To get your resulting sample 's', you'd calculate &#60;/p&#62;
&#60;p&#62;&#60;code&#62;&#60;br /&#62;
  n = (int) tSrc;&#60;br /&#62;
  nNext = (n + 1) % nSamples;&#60;br /&#62;
  sOut = src[n] * (1 - frac) + src[nNext] * (frac)&#60;br /&#62;
  tSrc = (tSrc + factor);&#60;br /&#62;
  if (tSrc &#38;gt; nSamples) tSrc -= nSamples;&#60;br /&#62;
&#60;/code&#62;&#60;/p&#62;
&#60;p&#62;This will work even if 'n' is integer, because then 'frac' will be 0.&#60;/p&#62;
&#60;p&#62;Now the above is expressed in floating-point; but you should be able to use fixed-point calculation fairly easily with some shifting and masking to get pretty good resolution in your interpolated samples - if you only need 6 bits for the integral part as in your example, then you can generously split a 32-bit integer into 8 integral bits and 24 fractional ones.&#60;/p&#62;
&#60;p&#62;You'd probably be better off using interrupts rather than delays, otherwise any amount of time spent on computation will change the sample-playback frequency and with it the pitch of the note you're trying to play; whereas if you use interrupts, your sample playback frequency will remain very nicely fixed. And if you do something like pre-calculate the next sample immediately after writing the current one, then each sample will be written to your PWM output at precise intervals.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22838</link>
			<pubDate>Thu, 07 Mar 2013 20:47:50 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22838@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Ah yes! I forgot to add, PWM is set to a prescaler of 3 and an overflow of 255 (I made the table for my arduino before I got my maple so changing it was a load of effort!) therefore, PWM speed is theoretically 94kHz (72e6/(3*255))&#60;/p&#62;
&#60;p&#62;The table is:&#60;br /&#62;
int sinearray[64] = {127, 139, 152, 164, 176, 187, 198, 208, 217, 225, 233, 239, 244, 249, 252, 253, 254, 253, 252, 249, 244, 239, 233, 225, 217, 208, 198, 187, 176, 164, 152, 139, 127, 115, 102, 90, 78, 67, 56, 46, 37, 29, 21, 15, 10, 5, 3, 2, 1, 2, 3, 5, 10, 15, 21, 29, 37, 46, 56, 67, 78, 90, 102, 115};
&#60;/p&#62;</description>
		</item>
		<item>
			<title>pyrohaz on "Forms of digital audio synthesis"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10329#post-22834</link>
			<pubDate>Thu, 07 Mar 2013 20:37:02 +0000</pubDate>
			<dc:creator>pyrohaz</dc:creator>
			<guid isPermaLink="false">22834@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Hey, i'm looking at audio synthesis and have succeeded in using DDS (Direct Digital Synthesis) implemented using a for loop and delayMicroseconds. I’ve also succeeded in doing this using the if, sample time method (kind of like arduino’s blink without delay) all I’m wondering though, the maximum frequency I need to produce is only 392Hz (G4) though frequencies below this, I need quite high precision. To keep to a high precision, I’m only using a 6bit sine array. Now as you can all imagine, 6 bit is pretty darn poor quality at only 64 values, an oscilloscope can quite clearly show the steps, especially at low frequencies. &#60;/p&#62;
&#60;p&#62;  for(aval = 0; aval&#38;lt;64; aval++){&#60;br /&#62;
    pwmWrite(sinearray[aval]);&#60;br /&#62;
    delayMicroseconds(Period);&#60;/p&#62;
&#60;p&#62;Period being 1/(2^bitdepth * F), in this case 1/(64F)&#60;/p&#62;
&#60;p&#62;As you can see, if I use this for a higher bit rate, say 8bit, producing 392Hz would require a delay time of 9.92uS, now since I don't know how to implement none integer delay times, that would have to be rounded to either 10uS or 9uS where at 10uS (closest rounding) will produce a value of 390.6Hz, not too far off but still producing a 3.5 cent error.&#60;/p&#62;
&#60;p&#62;What better ways are there for producing audio digitally? 10bit would be optimal but I can settle on 8bit! Would taking an interrupt route be better and setting the interrupt to write the table value to pwm every x microseconds? Where x is dependent on the frequency that I want to produce.&#60;/p&#62;
&#60;p&#62;Cheers,
&#60;/p&#62;</description>
		</item>

	</channel>
</rss>
