Home |
Search |
Today's Posts |
#1
|
|||
|
|||
Manipulate amplitude of 24 bit audio by 1dBFS or 6dBFS
Hi,
I am working on a project where the output is a 24 bit audio signal. I am using an FPGA chip to generate this audio signal. The input to the FPGA is a frequency value ( anywhere between 400hz to 10,000hz). Inside the FPGA, the frequency is converted to its amplitude by giving it to a sine look up table. The output 'A'is then manipulated in such a way( dividing it by 2) that the amplitude increments by a constant value ( for eg: 6 dBFS) The output 'A' is manipulated and given out of the FPGA as a serial data ( 24 bits) This 24 bit audio ouptut seems to have the correct frequency information. What I would like to know is..if this method is correct:that by dividing this output 'A' by a constant value 2, does it give a change of 6dBFS If so, would dividing the 'A' by 1.122 give me a change of 1dBFS? Or is there any other logic behind this? Any kind of help would be highly appreciated. Thankyou |
#2
|
|||
|
|||
yes
dB = 20 * log10 (x) where x is the voltage ratio techncailly that is dB which is a relative term. dBFS is dB relative to full scale. Mark Mark |
#3
|
|||
|
|||
Hi Mark,
Thankyou for replying. Yes I have come across this relationship between dB and voltage ratio. I have also come across this formula: dB= 20 * log 10 ( x/1677216) for a 24 bit where 2 ^ 24 = 1677216 So using this formula, I am able to calculate the dB value for any given bit value What I would like to know is...that lets say a particulat 24 bit value "X" represents -k dB What can be done to "X" in order to change the amplitude by a constant value ( for eg: 1 DB) I have come across something like this over the net: Dividing the 24 bit audio by 2 would cause a 6dB change. Is this correct? Thankyou |
#4
|
|||
|
|||
Yes I have come across this relationship between dB and voltage ratio. I have also come across this formula: dB= 20 * log 10 ( x/1677216) for a 24 bit where 2 ^ 24 = 1677216 I would think it would be 2^23 = 8388608 becasue one bit is the sighn bit (but I'm not sure about the standard representation used in 24 bit sytems) So using this formula, I am able to calculate the dB value for any given bit value Yes .. dB relative to full scale. You are just expressing the volatge ratio relative to full scale in dB What I would like to know is...that lets say a particulat 24 bit value "X" represents -k dB What can be done to "X" in order to change the amplitude by a constant value ( for eg: 1 DB) given the dB value, you determine the volatage ratio using x = 10^(dB/20) for example if dB = 1 then x= 1.122 so if you multiply by 1.122 that is increasing the signal by 1 dB if you divide by 1.122, that is reducing the signal by 1 dB I have come across something like this over the net: Dividing the 24 bit audio by 2 would cause a 6dB change. Is this correct? x=10^(dB/20) if dB = 6 then x = 1.9952 ~=2 yes. or x=10^(dB/20) if dB = -6 then x = 0.501 ~=0.5 of course dividing by 2 is the same as multiplyting by 0.5. These relative change formulas are true for any amount of bits. It is only when you want dBFS do you need to know how many bits you are using and what FULL SCALE is. Thankyou You're welcome Mark |
#5
|
|||
|
|||
genlock wrote:
So using this formula, I am able to calculate the dB value for any given bit value What I would like to know is...that lets say a particulat 24 bit value "X" represents -k dB What can be done to "X" in order to change the amplitude by a constant value ( for eg: 1 DB) If I understand your question correctly... A 1 dB change is a ratio of 2 to the power 1/20 = 1.035264924 So multiply the amplitude by that value N times in succession for +N dB and divide the amplitude by that N times in succession for -N dB Or in general for a N dB increase multiply by 2 to the power (N / 20) (and for a decrease N is negative and that formula still works) -- Anahata -+- http://www.treewind.co.uk Home: 01638 720444 Mob: 07976 263827 |
#6
|
|||
|
|||
Thanks Mark and Anahata,
What I want to do is vary the audio amplitude from 0dBFS to -30 dBFS in increments of 1 dB.... The audio amplitude is represented by a 24 bit binary value This is the output of the FPGA The input to the FPGA is the frequency information Whats happening inside the FPGA is that the frequency is converted to its amplitude This amplitude value is given to a variable "sample" which is 24 bits When sample is taken as the 24 bit output, its showing a value of 0dbFS What manipulation should I do to this "sample" to make it change in steps of 1? thankyou |
#7
|
|||
|
|||
I don't know what you're selling, but I'm leaving r.a.m in the
crosspost just in case... In rec.audio.marketplace,rec.audio.pro, on 1 Apr 2005 07:52:06 -0800, "genlock" wrote: Hi Mark, Thankyou for replying. Yes I have come across this relationship between dB and voltage ratio. I have also come across this formula: dB= 20 * log 10 ( x/1677216) for a 24 bit where 2 ^ 24 = 1677216 So using this formula, I am able to calculate the dB value for any given bit value What I would like to know is...that lets say a particulat 24 bit value "X" represents -k dB In that case it would be -k dBFS. as it's a dB measurement relative to the Full Scale value that can be represented as a digital value, in this case a 24-bit number. What can be done to "X" in order to change the amplitude by a constant value ( for eg: 1 DB) Do some algebra to solve your formula for X. Then you can put in a dBFS value (which will be less than or equal to 0) and get a value for X. Okay, you twisted my arm: X = (10 ^ (dBFS/20)) * 1677216 I have come across something like this over the net: Dividing the 24 bit audio by 2 would cause a 6dB change. Is this correct? Let's take your original formula and put in 1677216 for x: dBFS = 20 * log 10 ( x/1677216) for a 24 bit dBFS = 20 * log 10 ( 1677216/1677216) dBFS = 0 Divide the 1677216 in the numerator by two and do it again: dBFS= 20 * log 10 ( 838608/1677216) dBFS = -6.020599913 So, dividing the numeric value (which as someone else mentioned represents a voltage) by 2 (or equivalently in binary, shifting one bit to the right) gives a relative change of 6dB. The answer to ten significant figures is 6.020599914 and is of course more accurate and precise, but for most purposes it's fine to just round it to 6. To check the formula I gave above for X, I'll out in -6 which should give a number slightly greater than 838608 (for a ratio to full scale slightly greater than 1/2). X = (10 ^ (-6/20)) * 1677216 X = 840599.24723 Thankyou If you have more questions, you will get the best response in comp.dsp. ----- http://mindspring.com/~benbradley |
#8
|
|||
|
|||
So what you are saying is by just choosing the value of X, we can get
the desired dBFS output As in the example you showed , taking X= 838608...we get the output as -6dBFS When I use this technique inside the FPGA, the output 24 bit doesnt seem to have the right information whats happening is that: Frequency information is given as the input to the FPGA Inside the FPGA, this is fed into a sine conversion look up table....that gives out an output of 24 bits Lets name that sample Then this 24 bit sample is shifted right to get the output as -6dBFS The shift right seems to be working fine When I try to divide this 24 bit sample with the value 1.122..it should be giving me an output of -1dBFS Instead I am getting a random value no where close to the correct values Is this because the operation to be done is not exactly a division ? Do you have any idea about this? I would really appreciate it Thankyou |
#9
|
|||
|
|||
Is the hardware that does the divide by 1.122 working correctly?
Dividing (the voltage) by 1.122 should be the same as reducing the signal by 1dB. Sounds like there is a problem with your divide hardware. Are the word formats correct? Mark |
#10
|
|||
|
|||
genlock wrote:
Then this 24 bit sample is shifted right to get the output as -6dBFS The shift right seems to be working fine When I try to divide this 24 bit sample with the value 1.122..it should be giving me an output of -1dBFS What if you use the same divide operation, but give it 2 as the divisor? Instead I am getting a random value no where close to the correct values Is this because the operation to be done is not exactly a division ? No, I think your divide is broken. Try dividing by some easy values. --scott -- "C'est un Nagra. C'est suisse, et tres, tres precis." |
#11
|
|||
|
|||
The divide operation is working fine...What I mean to say is that the
hardware that does the divide is working correctly Its just that the right shift that is done in case of -6dBFS is not exactly doing a right shift What its doing is as follows: sample for 0dBFS sample (23) & sample(23 downto 1) for -6dBFS So as u can see, its retaining the 23rd bit as the MSB and shifting the 23 to 1 bits to the right What is the significance of retaining this 23rd bit every time For instance, in the case of -12dBFS its as follows: sample(23) & sample(23) & sample(23 downto 2) So I am thinking that maybe its not exactly a division operation That could be the reason why I am gettting random values when I do a division by 1.122 for -1dBFS Any ideas about this? Thankyou |
#12
|
|||
|
|||
On 1 Apr 2005 12:19:12 -0800, "genlock" wrote:
So what you are saying is by just choosing the value of X, we can get the desired dBFS output As in the example you showed , taking X= 838608...we get the output as -6dBFS When I use this technique inside the FPGA, the output 24 bit doesnt seem to have the right information whats happening is that: Frequency information is given as the input to the FPGA Inside the FPGA, this is fed into a sine conversion look up table....that gives out an output of 24 bits Lets name that sample Then this 24 bit sample is shifted right to get the output as -6dBFS The shift right seems to be working fine Shifting is effectively, for this application, multiplication by powers of 2. Shifting right one bit is multiplying by 0.5, or -6dB. Shifting right two bits is multiplying by 0.25, or -12dB. If 6dB steps are good enough, then shifting will be all you need. When I try to divide this 24 bit sample with the value 1.122..it should be giving me an output of -1dBFS That would work fine if your divide were for values of type float in a C program on a general-purpose desktop PC, but I doubt you want to stick something into an FPGA to do floating point just to handle this one operation, especially when it's not neccesary. As others say, there's probably something wrong with the divide, but dividing is the wrong function to use anyway when you can multiply by the reciprocal. So on't do a divide. Do a multiply. Have a 24 bit word, call it amplitude. Multiply amplitude by sample, and you'll get a 48-bit product. Take the high 24 bits of this product, and use this as your final output value. This is effectively fixed-point arithmetic, where the 24 bit values have a binary point at the left, and represent numbers between -1 and 1 (exclusively). It's real useful for doing fractional math with integer operations. If you can eliminate the part of the multiply that generates the lower 24 bit word, you can save some circuitry in the FPGA, but that's just some optional optimization. Take the value 1.122. get its reciprocal (you may want to use a more precise value than those four significant digits, OTOH, is it that critical that your outputs be within a small fraction of the dB value you claim it to be? You decide), which to four figures is .8913. Multiply this by the max 24 bit value, 16777216, and you get 14951854.8992, or you can just truncate it to 14951854. This will be your 24-bit amplitude value to multiply against the sine table values, as instructed above, to give an output of -1dBFS. And of course that only works as-is for the first 180 degrees of the sinewave, I presume you're handling the sign and all for the whole 360 degrees. Instead I am getting a random value no where close to the correct values Is this because the operation to be done is not exactly a division ? Do you have any idea about this? I would really appreciate it Thankyou ----- http://mindspring.com/~benbradley |
#13
|
|||
|
|||
Hi Ben,
I tried doing exactly what you have mentioned here above..... I tried multiplying instead of dividing Still the output doesnt give me the correct values I am also losing the frequency information when I connect the output of the FPGA to the audio measurement set. The frequency information isnt lost when I am doing the shift operation in case of -6dBFS increments Thats the reason why I was wondering if something else is being done in case of -6dBFS coz that seems to be giving fine outputs( when seen in the audio measurement set) Do you any idea about dither? Should I do some dithering to the truncated 24 bits before I could give it as the output Lemme know if you have some ideas abt this. I appreciate you helping me out. Thankyou . |
#14
|
|||
|
|||
genlock wrote:
So as u can see, its retaining the 23rd bit as the MSB and shifting the 23 to 1 bits to the right What is the significance of retaining this 23rd bit every time You are doing twos complement arithmetic. The top bit is the sign. When you divide, you need also to be using twos complement and not just treating it like an unsigned int. --scott -- "C'est un Nagra. C'est suisse, et tres, tres precis." |
#15
|
|||
|
|||
Are you saying that I need to first divide/Multiply and then get the
2's complement of that...and give that as the output? Correct me if I am wrong Or do you mean to say that I should get the 2's complement of the "sample" before I divide/multiply it? Thankyou |
#16
|
|||
|
|||
"genlock" wrote in message oups.com... Hi Ben, I tried doing exactly what you have mentioned here above..... I tried multiplying instead of dividing Still the output doesnt give me the correct values I am also losing the frequency information when I connect the output of the FPGA to the audio measurement set. The frequency information isnt lost when I am doing the shift operation in case of -6dBFS increments Thats the reason why I was wondering if something else is being done in case of -6dBFS coz that seems to be giving fine outputs( when seen in the audio measurement set) Do you any idea about dither? Should I do some dithering to the truncated 24 bits before I could give it as the output Lemme know if you have some ideas abt this. I appreciate you helping me out. Thankyou . Are you doing two-s-complement math? Audio data is represented in two's-complement format. Mike P. |
#17
|
|||
|
|||
Hi,
I am not doing 2's complement math. The only place where the 2's complement is taking place is as follows: Inside the FPGA, the input frequency is given to a value "theta" We then calculate x = theta* ( 2pi/2 ^ theta_width)[ theta_width is 10 bits here] We then calculate sin (x) [ I think this is in 2's complement form] this sin(x) is given to "sample" [24 bits wide] Sample is then shifted right in the following way: sample (23) & sample (23 downto 1) for -6 dBFS [ the 23rd bit of sample is concatenated with 23 to 1 bits of sample ] This seems to work right and gives the correct output But when I do this: Multiply sample with 1/1.122 to get -1 dBFS , I dont get the correct output I am clearly losing some information since shifting right can be done only if we want to divide/multiply by 2. Thanks |
#18
|
|||
|
|||
genlock wrote:
Are you saying that I need to first divide/Multiply and then get the 2's complement of that...and give that as the output? No, you need to use the twos-complement signed division operation. You are multiplying signed ints, not unsigned ints. If you really want to, you can shift left, preserve the sign, do your division with an unsigned word, then shift right and restore the sign. That's at least two machine cycles at minimum, though. --scott -- "C'est un Nagra. C'est suisse, et tres, tres precis." |
#19
|
|||
|
|||
Shifting left and shifting right is going to multiply and divide it by
2 what I would want to do is by the value 1.122 So I must go in for twos-complement signed division operation then? Am I right Thankyou |
#20
|
|||
|
|||
genlock wrote:
I am not doing 2's complement math. Yes. You should be, because the output you're producing is a signed int. At least, it SHOULD be one if it's going into an S-PDIF device. --scott -- "C'est un Nagra. C'est suisse, et tres, tres precis." |
#21
|
|||
|
|||
genlock wrote:
Shifting left and shifting right is going to multiply and divide it by 2 Right, but you don't care about that. What you want to do is to shift the sign off, store it, and then shift it back and restore the sign. Multiplying by 2 is a side-effect but one you don't really care much about. Another way of doing this would be to AND with a mask that preserved only the top bit, then AND with a mask that cleared the top bit, do the unsigned math, check for overflow, then OR the sign back on. That wastes a good dozen cycles, though. If your processor doesn't have signed operations, the shift-and-work-with twice-the-value trick will save a lot of cycles. what I would want to do is by the value 1.122 So I must go in for twos-complement signed division operation then? If you are multiplying a signed int, you need to be using the signed division instruction. Have you ever programmed in assembler before? --scott -- "C'est un Nagra. C'est suisse, et tres, tres precis." |
#22
|
|||
|
|||
genlock wrote:
Are you saying that I need to first divide/Multiply and then get the 2's complement of that...and give that as the output? Correct me if I am wrong Or do you mean to say that I should get the 2's complement of the "sample" before I divide/multiply it? I haven't been following the thread, but I'm pretty sure what he's saying is that you need to use a multiply or divide instruction that knows it's operating on a two's-complement number. Let me use four-bit integers as an example. Let's say you have the value 1100. 10000 - 1100 == 0100, so that means that 1100 == -4. Let's say you want to divide 1100 (-4) by 2. The result should be -2, right? That means 1100 div 0010 == 1110. (1110 == 2 because 10000 - 1110 == 0010.) But let's say you used an unsigned division operator to divide by 2 instead. Then you would just be shifting right one position and filling the left with zeros. That gives you a different answer. The point is, signed division and unsigned division are two distinct operations. If you call the these operations div.s and div.u (respectively), then you can say: 1100 div.s 0010 == 1110 (-4 / 2 == -2) 1100 div.u 0010 == 0110 (12 / 2 == 6) They don't always just differ in the leftmost bit either. For example: 1100 div.s 0100 == 1111 (-4 / 4 == -1) 1100 div.u 0100 == 0011 (12 / 4 == 3) Another way of looking at this is that two's-complement uses a particular "region" of the (discrete) number line differently: bit string unsigned val two's-complement val ---------- ------------ -------------------- 0000 0 0 0001 1 1 0010 2 2 0011 3 3 0100 4 4 0101 5 5 0110 6 6 0111 7 7 1000 8 -8 1001 9 -7 1010 10 -6 1011 11 -5 1100 12 -4 1101 13 -3 1110 14 -2 1111 15 -1 These numbers have the following property: (twos-complement-value (some-N-bit-quantity)) mod 2^N == (unsigned_int_value (the-same-N-bit-quantity)) mod 2^N BUT, that doesn't mean they have the same division or multiplcation operators. (However, it DOES mean they have the same addition and subtraction operators!) Hope that helps. - Logan |
#23
|
|||
|
|||
On 1 Apr 2005 14:06:29 -0800, "genlock" wrote:
Hi Ben, I tried doing exactly what you have mentioned here above..... I tried multiplying instead of dividing Still the output doesnt give me the correct values I agree with the others, you should be doing signed arithmetic. I am also losing the frequency information when I connect the output of the FPGA to the audio measurement set. The frequency information isnt lost when I am doing the shift operation in case of -6dBFS increments If the output isn't giving the correct values, you probably won't be able to read a good frequency output. Thats the reason why I was wondering if something else is being done in case of -6dBFS coz that seems to be giving fine outputs( when seen in the audio measurement set) Do you any idea about dither? Dither can take something that's already working and make it better. It crossed my mind to say something about dither, but with 24 bits the residual distortion is already so low you almost certainly don't need dither. If you want to decrease distortion to near-theoretically low levels, you would probably do better to use a larger sine table and/or do linear interpolation. But if you want to learn about dither (you may need to use it in other systems), go to http://digido.com and click on articles, then dither article. Should I do some dithering to the truncated 24 bits before I could give it as the output Lemme know if you have some ideas abt this. I appreciate you helping me out. Thankyou . ----- http://mindspring.com/~benbradley |
Reply |
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Forum | |||
common mode rejection vs. crosstalk | Pro Audio | |||
Artists cut out the record biz | Pro Audio |