DIY DSP for Digital Room Correction - Page 11 - diyAudio
 DIY DSP for Digital Room Correction
 User Name Stay logged in? Password
 Home Forums Rules Articles diyAudio Store Gallery Wiki Blogs Register Donations FAQ Calendar Search Today's Posts Mark Forums Read Search

 Digital Source Digital Players and Recorders: CD , SACD , Tape, Memory Card, etc.

 Please consider donating to help us continue to serve you. Ads on/off / Custom Title / More PMs / More album space / Advanced printing & mass image saving
diyAudio Member

Join Date: Jan 2002
Location: The Netherlands
Quote:
 If I create my own simple "filter" by entering coeffs manually in a text file I can actually get some sort of filtering happening now without tons of distortion / clipping. When I say a simple filter, I mean very simple like using taps of 1 2 3 4 5 repeating every 32 taps or something like that - I'm not using proper filter coeffs yet due to the problems below....
@Ozone
I have done my FIR core in VHDL and i can supply you with the code if you like.
A practical hint: When testing the FIR do a simulation with actual coefficients and start testing by supplying a '1' to the system, followed by zero data. When all goes well the coeffiecients come out again.

@Wingfeather
Quote:
 For 32-bit filter coefficients, I tend to use a 2.30 format, since filter coefficients often require a range between plus- and minus-two.
It is a question of scaling is it ?

best regards

Simon

diyAudio Member

Join Date: Mar 2003
Location: Mountain View, CA
Quote:
 Originally posted by blu_line Please elaborate !
I don't know exactly what you're asking, but I'll expand a little on what I meant by "2.30 format".

Fractional binary could be described as 1.(n-1), in that there is one bit to the left of the decimal place and n-1 bits to the right. Since the value of this bit that's to the left of the decimal point is -1, this fractional number system is capable of representing numbers between -1 and 1 - (2 ^ -(n-1)). This is generally how it is thought of, although, as I said in my previous post, the existence of a decimal place is really just a nice imaginary detail that simplifies things.

The problem is that, in IIR filters at least, you often want coefficients that are greater than 1 in magnitude. They can be very large at times, depending on the filter you want, and that's a problem. But most of the time I've personally found a range of plus/minus-two to be fine. In order to do this you move the figurative decimal point one place to the right, to give you a 2.(n-2) format. This doesn't really change anything on it's own, since the binary pattern you get from the multiplier is the same. However, the weighting of the bits at the output is now different and it's important that this is remembered when doing subsequent operations.

In order to use the output of a filter based on the 2.30 format (or, to be clear, a filter based on the 1.31 format for the audio data and the 2.30 format for the coefficients) for a DAC, for example, you must remember to shift values left by one place before outputting them, or else you'll be introducing a gain of -6dB and also losing one bit of resolution. This shift means that it's now possible for things to clip at this stage, so it's important to be careful.
__________________
Wingfeather

 23rd January 2008, 05:55 AM #103 Account Disabled   Join Date: Jan 2006 Location: whereisit Uh, why not just use floating point? Much harder to mess up. And don't forget that when you use a FIR, intersample peaks over 0 dB can be generated, and there's no amount of headroom that can guarantee they won't occur for every possible input.
diyAudio Member

Join Date: Mar 2003
Location: Mountain View, CA
Quote:
 Originally posted by abzug Uh, why not just use floating point? Much harder to mess up.
Implementing floating-point on an FPGA might be a bit of a pain (though there are presumably libraries for this...). Besides, it has its own problems, uses lots more logic, and can't be dithered. Floating point using lots of bits is okay, but the problems of logic usage and general fussyness get worse. I guess it could be worth a try eventually, but I think the OP is having trouble enough with fixed-point so far!

Quote:
 Originally posted by abzug there's no amount of headroom that can guarantee they won't occur for every possible input
Not true - the maximum output that can occur is very easy to calculate for an FIR filter. The maximum instantaneous output you can get is when the audio samples are all full scale, with their signs matching that of their respective coefficients. In other words, it's the sum of the magnitudes of all of the coefficients.
__________________
Wingfeather

Account Disabled

Join Date: Jan 2006
Location: whereisit
Quote:
 Originally posted by Wingfeather it's the sum of the magnitudes of all of the coefficients.
Oops, you are correct, my mistake.
Sounds like a good reason that every FIR should be normalized.

 26th January 2008, 04:54 PM #106 diyAudio Member   Join Date: Mar 2003 Location: Mountain View, CA Well, sorta - it would introduce some gain though. But if you want some gain anyway then I guess amplifying the coefficients is as good a way as any. __________________ Wingfeather
 7th June 2008, 08:03 PM #107 diyAudio Member   Join Date: Jul 2005 Location: Devon Hi all, OK, I really want to get back into this again big time. I'll be building my first chipamp very soon when the parts arrive (Mauro RevC), and I want to integrate an FPGA board with the amp (plus some DACs).... I've been doing some more reading about DSPs etc. and I've been trying to get my head around this Q15 format thing for months now. I can get the general idea, but it still has me stumped as to where exactly the changes need to be made in the way things are calculated. (It's near impossible to find any code examples in Verilog or VHDL for this sort of thing.) The best way to explain this is to tell you what I understand so far.... One common use of the Q15 format is for when you want a way of constraining the result of a multiply operation when using a fixed-point DSP. This is mainly so the result cannot overflow, but it has other benefits / drawbacks depending on what you need.... An example of using Q15 would be if wanted to do a MAC between an audio input sample and a filter coefficient.... On a 16-bit fixed-point DSP, if your two numbers (sample and filter coef) are represented as integers, the result of a multiply is very likely to cause an overflow (since you're likely to want your output to also be 16 bits).... The idea of the Q15 format is to represent your two numbers as fractions instead of integers. This would mean that when the two numbers are multiplied together, the result will always be less than 1 (will not overflow / clip your output). ie. normally, I2S input samples are 16-bit signed (-32768 to +32767). The Q15 format represents the useable range as being between -1 and 1 (technically, the maximum is just below 1 due to the quantization of 15 bits?? AFAIUI) In Q15, the MSB is the sign bit, but it's common in most DSP purposes for the sign bit to be ignored because you often want the inputs and results to stay "minus" anyway (less than 1). The part I'm stuck on is whether you need to "convert" your input samples and / or coeffs into the Q15 format first, or if the idea is that the multilplier logic stays the same (as with integers), but you need to scale the results before and / or after the multiply??? In other words, if you assume the incoming I2S audio samples are 16-bit signed numbers, how would I convert these samples to the Q15 format, or do I even need to? Is it simply a case of finding the correct method of scaling the samples before / after calculation, or is a conversion necessary first? I've seen that you can scale the binary representations back to the "real" fractions by multiplying or dividing by 32767, but is this only needed to check the "real" results? (I'm only interested in how the logic needs to operate on the fixed-point binary numbers inside the FPGA - the 32767 thing confuses things for me.) I can understand that in the Q15 format, you "think" of the binary point (binary equivalent of the decimal point) as being to the left of bit 15, so does the use of Q15 require a change to the majority of the logic, or was the whole idea of the Q format to keep most logic the same, and only change the input / result scaling? ie. is it more of a binary "trick" than a format as such? Ok, I also see that when you multiply two Q15 numbers together you end up with a Q30 number (32 bits = two sign bits + 30 "fraction" bits). To "scale" this back to 16 bits, you can simply shift left by one bit, then take the top 16 bits of the 32 bit number as your result. (those 16 bits can be easily routed directly to the next processing stage in an FPGA.) It's been very frustrating trying to find any simplified info on the Web regarding DSPs and data formats etc. I can see why many people have recommended books before (sorry, what is this "book" thing exactly?!) Some of the few precious pages I found that explain things in layman's terms (well, almost). (pages 28 to 33).... http://www.elin.ttu.ee/~olev/lect1.pdf And page 8.... http://www.fulton.asu.edu/~karam/rea...s2.ppt#345,8,Q format Multiplication So, how would I need to scale / convert the incoming audio samples (assuming it's 16 bit "two's" I2S for now.), and how would I go about converting my coefficients from 32 bit float or 16 bit PCM files to Q15 format? (I realize there are such things as floating point DSP chips, but I need help to understand the fixed point stuff first.) I know this is a big ask for one post, but any help would be more than appreciated. Thanks in advance for any suggestions. OzOnE. P.S. I also understand the need for scaling the coeffs to ensure that the maximum result of the whole FIR filter does not clip the output at any time. I've also read about truncation / rounding / dithering etc., but this could probably wait a while until the Q15 thing makes more sense.
 8th June 2008, 12:34 PM #108 diyAudio Member   Join Date: Jul 2005 Location: Devon Hi, I did some more reading last night and I've started to make sense of some of this. I think the main confusion is that things are dependant on which "realm" they are in. ie. "real" or "binary / hex". The real numbers only exist on say the PC side and the filter coeffs need to be converted to Q15 first so a fixed-point DSP can process them.... I did a simple practical example of multiplying (using the Q15 format)... I took two random (arbitrary) "real" numbers of 0.23 and 0.38, and converted these to Q15 - I scaled them by first multiplying them by 32767 (the Q15 coeff?)... 0.23 x 32767 = 7536 = 1D70 in HEX 0.38 x 32767 = 12451 = 30A3 in HEX These numbers have been rounded when stored as Q15 due to quantization (I think that's the general term). I then took the hex Q15 numbers and multiplied... 1D70 x 30A3 = 597BE50 (Q30 hex?)... During the initial multiply, the "Q15 coefficient" (32767) applied to the original "real" numbers gets multiplied too, so you need to scale this back down again to get the proper Q15 result.... 597BE50 / 7FFF = B2F This now gives us the Q15 result of the multiply. ie. B2F (hex) = 2863 (decimal).... Convert to "real" again: 2863 / 32767 = 0.08737449 etc. What I couldn't get to work is shifting the Q30 result bits left, then taking the top 16 bits as the Q15 result? So, I can see now that the Q15 format is basically a way of representing the real data inside a fixed-point DSP. The input data has to be converted / scaled first, and some logic has to be changed or added to calculate the correct result(s). Ok, so if my input audio data is 16-bit signed (-32768 to 32767), how would I normalize using binary operations to make the samples less than 1 and convert to Q15? Or, do I even need to convert the samples? I hope this can help others too, but please don't take all of this as accurate, as I'm not 100% on anything yet. OzOnE.
 9th June 2008, 05:24 AM #109 diyAudio Member   Join Date: Nov 2007 My impression from reading those slides is that you don't need to do anything to go between two's complement int and Q15. It's a matter of reinterpreting where the decimal point goes, and using different rules for multiplication. For example, we can multiply 3 by 4 to get 12. We can also multiply 0.3 and 0.4 to get 0.12, but we have to remember to "add the decimals" or whatever they called it back in grade school. Looking around, people seem to use 32768 as the Q15 multiplier. This makes multiplies and divides clean 15-bit shifts. Going with your example again: 0.23 x 32768 = 7537 = 0x1d71 0.38 x 32768 = 12452 = 0x30a4 0x1d71 x 0x30a4 = 0x5980C64, or 0000 0101 1001 1000 0000 1100 0110 0100 (result in bold) 0000 1011 0011 0000 = 0xB30 = 2864 2864 / 32768 = 0.0874 Sanity check: 0.23 x 0.38 = 0.0874 If we had been working under the int paradigm, we'd have gotten 7537 x 12452 = 93850724 which overflows. But by reinterpreting ints as Q15, we can multiply without worrying about overflow.
 9th June 2008, 03:19 PM #110 diyAudio Member   Join Date: Jul 2005 Location: Devon Hi, @mako - thanks for the sanity check. I've now found the glaring mistake in why I couldn't "take the top bits". You see, I was using Windoze Calculator to test the theory, and when it gives the answer in binary, it of course doesn't show all the leading zero's! (only 27 bits)... So, when I took the new answer, the bits were shifted way to far to the right..... 0x5980C64 = 101 1001 1000 0000 1100 0110 0100 I should have noticed they weren't in groups of four bits. Anyway, that's good because I can now simply take the top bits directly as my result in the FPGA design (ignoring extended sign bit). This will mean simply routing the 16 result bits directly instead of doing a logic divide (probably gets routed the same way anyway if the divide is a power of two though.) It does look like using 32768 is better as it rounds things closer to the real result. The question is, is taking the top bits of the result (apart from the first bit) the same as dividing by 32768 or 32767 ? (btw, I've already changed most of the logic in the design to work with Q format coeffs.) I'm now just looking for a simple CD player or something to test it out on. I was using a DVB-T digibox before, but I really need something with a repeatable audio stream. I suppose I could use an old sound card, but a lot of these have crappy integrated DACs (no I2S pins). The other thing is that I only have one FPGA board atm, and I'm using it on my LED projector design. I'm not sure which new FPGA I should buy for the DSP work until I know how much power / logic is really required, so I'll have to borrow the other board again for now. I think I understand that the DAC data is also in the range of -32768 to 32767, so the Q15 coeffs should produce the correct result when multiplied / accumulated etc. I think what people were saying before (ie. wingfeather) was that without rounding the result before taking the top bits, the output samples would give a -0.5 LSB error, and hence a very small DC offset on the DAC - is this roughly what was meant? Ok, so when the results of the FIR are accumulated, they can still overflow - to prevent this from happening, is the general idea just to scale the input samples down by a power of two first? (after deciding a suitable scale factor.) Or is it standard practive to just scale the coeffs first? What worries me about this DSP stuff is that it seems quite difficult to find information on things without finding tons of white papers with complex algebra on. I don't know a thing about theta / delta / sigma / pi / cake! - why are there not many step-by-step examples about FIR? Things like the following are great for playing with, but they don't show the underlying process of the taps etc.... http://www.htwm.de/vannacke/dfilter/index2.html What I'm looking for is a simulator where you can add logic blocks in, pass some audio through and hear the results in realtime (especially good if it shows the Q format at work). This could also allow you to see the results one sample at a time. I'm sure software like matlab is great for this, but it's also quite expensive. Once I got my head around FIR filtering (still a long way to go), all I really needed to know was something like.... 1. Take 32-bit float coeffs (or whatever format you have) 2. "Normalize" coeffs to be between -1 and 1 3. Convert coeffs to Q15 (multiply by 32768 and store as 15 bits (+ sign.) 4. Create circular buffer of "x taps" and input one audio sample at a time into buffer (16 bit two's format) 5. Multiply every sample currently in the buffer by it's corresponding coeff. 6. Take the top bits of the multiply to convert result back to Q15 (divide down again). 7. Store Q15 multiply results in accumulator until all taps processed. 8. Output the result from the accumulator to the DAC (after possible scaling.) 9. Shift all audio samples through the taps one place and receive next new sample onto first tap (ie. update circular buffer pointer.) 10. Repeat 5 Again, not exactly a complete explanation, but it's taken me about a year to get this far - I can see the point of understanding the process first, but surely there's a better way for the information to be demonstrated? I'm very greatful for all the help received on this forum, and I realize that I should help my own naivety and actually read a book for once, so with that in mind, I'll look out for some of the book suggestions I've had so far. The main thing driving me along is that I'm convinced that long FIR filters can be produced in a far more cost effective way using an FPGA and that expensive DSP solutions aren't necessarily needed. The beauty of FPGA's is that you design the logic around your goal so you utilize things in the most efficient way. I think I'll test this with 16 bit audio and Q15 filter coeffs first before worrying about 24 bit audio and 32 bit coeffs! OzOnE. P.S. Sorry the essay - again!

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are Off Pingbacks are Off Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post kipman725 Multi-Way 3 7th August 2009 12:13 PM mr.duck Digital Line Level 1 23rd June 2009 04:49 PM wigginjs Multi-Way 37 24th February 2008 06:10 PM Radian Multi-Way 1 7th February 2007 07:10 PM

 New To Site? Need Help?

All times are GMT. The time now is 08:22 AM.