View previous topic :: View next topic |
Author |
Message |
Skirmitt
Joined: 19 May 2009 Posts: 60
|
Mixing audio - INT speed problem |
Posted: Wed May 27, 2015 2:38 am |
|
|
I have a project that plays 2 sound files at once (mixed). There are large sounds stored on an SD card and small sounds stored in the flash of the PIC. I use a 18f2525 with the INTOSC at 32 MHz.
The sound from timer 1 needs to have a variable pitch. Timer 0 sound has fixed pitch.
Problem is that when I mix the sounds the pitch from timer 0 sounds not constant. I guess there is not enough time left to process everything. I did have to add HIGH priority to Timer 1 to fix the issue there. Would there be a way to fix it with timer 0 ?
Or am I at the max capabilities of the PIC.
Overclocking the PIC with crystal at 48 MHz did not help
Code: |
#int_timer0
timer0_isr()
{
set_timer0(65440);
//set_timer0( get_timer0() + 65440); //tried this also, did not work
if(playgear==1)
{
dg=(int)gear[ig];
ig++;
if(ig==GEAR_LENGTH)
{
ig=0;
playgear=0;
dg=128;
}
}
}
#int_timer1 HIGH
void timer1_isr()
{
set_timer1(timerpit); //variable pitch
if (ReadPos != WritePos)
{
output=((int32)buffer1[ReadPos]+(int32)dr+(int32)db+(int32)dg)/4;
output_b(output);
int16 TempPos = ReadPos;
TempPos++;
if (TempPos == BUFF_SIZE)
ReadPos = 0;
else
ReadPos = TempPos;
}
}
|
Timer config:
Code: |
setup_timer_0(t0_DIV_8 );
setup_timer_1(t1_internal | t1_div_by_8 );
setup_timer_3(t3_internal | t3_div_by_8 );
enable_interrupts(int_timer0);
enable_interrupts(int_timer1);
enable_interrupts(int_timer3);
enable_interrupts(INT_RDA);
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed May 27, 2015 4:55 am |
|
|
Don't know the 'format' of the 'music files' but I'll guess and say its beyond the PICs ability. There's a guy 'Black ???' that has a 1 bit sound program, been around for years, might be helpful.
In the 'old days' I'd just slap an 8 bit ISA sound card onto an '877. At 20 Megs it could handle the data transfers but memory was the 'bottleneck'. Yeesh that was 15-20 years ago....
Jay |
|
|
Skirmitt
Joined: 19 May 2009 Posts: 60
|
|
Posted: Wed May 27, 2015 5:13 am |
|
|
It is 8 bit uncompressed PCM audio at 16 - 22 KHz.
Playing 1 stream is no problem and I don't feel that that is stressing the PIC. It feels like the duration of the INT handler is not constant when using 2 timers. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Wed May 27, 2015 7:06 am |
|
|
If you use the timers without 'high', the duration _will_ be constant, _but_ the actual call to whichever handler occurs second, can be delayed by the duration of the first.
With high, the duration of the 'non high' handler can be increased by the duration of the high handler.
Both your handlers are rather slow/bulky. Realistically to do things like this with accurate timings, needs you to look carefully at the time involved in every line, and possibly consider 'cheat' approaches (working from a smaller buffer inside the ISR for example, and just 'swapping' buffers as they are used). Also things would be a lot better if you could reduce the number of ISR's involved. One single high frequency task would be better, and possibly not using ISR's at all. For instance, I do some BLDC motor applications involving synthesised variable width multi-phase PWM at 50KHz. This is done without ISR's at all. Instead the code uses the CCP, and _polls_ it's interrupt flag. It also tests for serial by polling the serial flag _only_ at the end of the cycle in the 'deadtime' before the next pulse. On a 48MHz PIC, six waveforms are all synthesised without a single missing cycle.... |
|
|
Skirmitt
Joined: 19 May 2009 Posts: 60
|
|
Posted: Wed May 27, 2015 8:49 am |
|
|
I tried a few things. One was toggling a pin in the timer 0 isr and this showed on the scope what I suspected, the frequency is not constant so probably timer 1 interrupts too much for the pic.
My knowledge does not reach far enough to implement your suggested aproach although I do understand what you want to do.
Would it be possible to use timer 1 to produce both 16 Khz data and 22 KHz where the 22KHz stream can be pitched.
I know presetting it to 65490 gives me around 22 Khz so I would need to calculate what the next preset would be to add the second sound. Would that be a possibility ? |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Thu May 28, 2015 6:23 am |
|
|
To my way of thinking the two different interrupt rates are always going to create an issue; when they interrupt at or near the same time then one will take precedence and throw the other one off as it has to wait for completion.
This is something I'd be interested in figuring out, I myself am playing back multiple mixed raw 8bit PCMs @16kHz but no dynamic timing changes. But it's late and my brain isn't engaging, so I'll come back to it tomorrow (when I should be doing, you know, work)
I'm vaguely thinking something with flags and state machines, but my mental machinery wants to go to beddy-byes |
|
|
Skirmitt
Joined: 19 May 2009 Posts: 60
|
|
Posted: Thu May 28, 2015 6:29 am |
|
|
Exactly, I guess no matter how fast the pic is working it will always be an issue.
I'm curious what your solution would be ! |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Thu May 28, 2015 6:47 am |
|
|
OK, last thought on the way to bed, do you actually NEED to change the timing, or can it be achieved in a faux way? eg. pitched microsamples? So just use the one interrupt for playback, and depending on the input status choose a certain pitched microsample to suit?
I don't know what you are trying to achieve, I'm envisaging something like those sound systems for RC planes that have a few big "startup" and "shutdown" sounds mixed with variable-pitched engine sounds tied into the revs... which to me would work fine/great with microsamples. |
|
|
Skirmitt
Joined: 19 May 2009 Posts: 60
|
|
Posted: Thu May 28, 2015 6:56 am |
|
|
Exactly, it is a sound system for RC trucks. Microsamples would be ok but pitching is a bit better because then I have more control. |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Thu May 28, 2015 10:15 pm |
|
|
Does the variable rate work by itself? ie. without the 16kHz stream? If so, obviously not an ideal solution, but why not just use two PICs, with one doing nothing but the variable stream and listening to commands from the primary?
Got any examples (eg. youtube) of the sort of sound you want to achieve? eg. here's a plain one from hobbyking:
https://www.youtube.com/watch?v=mV0ZuAz5fSY, seems to me that if you split it into say a max of 10 pitch tables it should still give pretty good response to throttle, maybe you could also fudge it and double the "throttle resolution" by mixing two neighbouring pitches at mid-pitch? So when it's "on pitch" mix the same waveform twice, when it's "mid-pitch" mix the lower and upper waveforms from the table (eg. 80Hz and 90Hz to fudge 85Hz). You can do this by soft-addition if you make 7bit samples (halve the volume and shift "down" by 64 samples), or if you hard-add them (two sound outputs) you can use two 8bit waveforms to effectively get 9bit.
But I don't know what kind of sounds a truck system (what kind of "truck"? Semi, Hummer, Monster, rock-crawler...?) is supposed to produce |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Fri May 29, 2015 12:35 am |
|
|
RoGuE_StreaK's suggestion is basically good.
Generate the sound with a chip like the PIC16F1508. Suddenly this job is easy. A few lines of code does the whole thing, without timing problems..... |
|
|
Skirmitt
Joined: 19 May 2009 Posts: 60
|
|
Posted: Fri May 29, 2015 6:24 am |
|
|
The sounds are prerecorded ones I made with a microphone.
The board itself already has 2 PIC's on it. One 16F that reads all the servo signals with a timer and controls the lights. The other one (18F) does alle the sound.
I have sound for idle, leave, stop, driving and shut down. That alone works like a charm and is bugfree.
I wanted to add sounds for example air release, horn, reverse beep etc. But those have to played at a fixed rate.
So, a third PIC is a no go, for this design that is since the PCB is ready.
For now the only solution will be to prevent the primary sound from pitching I guess.
Making separate samples would involve a lot of time and overhauling my code. |
|
|
|