|
Largie
Posts: 110
|
 |
« on: 16 May '02 - 23:24 » |
Quote
|
Does anybody know any filter or logic that can make every output at the same level. I am currently making a player that play mp3 sounds and am using bass. I have heard that is it is a system where you 40% sound loss on every tune, but the output level is the same regardless of how much the level really are. Any clue anyone?! 
|
|
|
|
|
Logged
|
|
|
|
|
wombat
Posts: 29
|
 |
« Reply #1 on: 17 May '02 - 10:36 » |
Quote
|
There are two solutions for that... neither one is perfect.
First option: Decode the whole output to memory first, check the average sound level _or_ the loudest peak, and normalize accordingly during playback (use a DSP routine for that).
Second option: Dynamically adjust the gain level by using some kind of prebuffering (say, buffer 2 secs ahead) and then calculate the gain. This will mess up royally if your mp3/mod has a quiet piece in it.
For averaging the volume: You can usually assume that the average of all your sample values is _roughly_ 1/3rd of the peak value. So, get the average of whatever buffer you chose, then calculate the difference between your desired volume (divide by three) and your average. This gives you a multiplier which you can use in your DSP procedure.
If you go for peak value, you might get odd results if the original recording is noisy and has spikes. It does usually work well for clean CD-rips though.
|
|
|
|
|
Logged
|
|
|
|
|
Sl@jaR
Posts: 81
|
 |
« Reply #2 on: 17 May '02 - 12:02 » |
Quote
|
The first version is the only one which is a normalization  The second one would be a compression, but i don't think it's good. Realtime Normalization isn't possible... --> you cann't normalize streams.
|
|
|
|
|
Logged
|
|
|
|
|
wombat
Posts: 29
|
 |
« Reply #3 on: 17 May '02 - 12:37 » |
Quote
|
It can be done for file streams _and_ live streams, if you prebuffer them enough. It's admittedly a pain in the rearside, but I'd think it would be doable with BASS by combining the raw output functions with stream input and whatnot...
Btw, one program which does dynamic gain is ModPlug Player.
|
|
|
|
|
Logged
|
|
|
|
|
Sl@jaR
Posts: 81
|
 |
« Reply #4 on: 17 May '02 - 12:45 » |
Quote
|
but it's not a exact normalization 
|
|
|
|
|
Logged
|
|
|
|
|
wombat
Posts: 29
|
 |
« Reply #5 on: 17 May '02 - 12:54 » |
Quote
|
True... more like dynamic gain control (I think they even call it that in the software)
|
|
|
|
|
Logged
|
|
|
|
|
Largie
Posts: 110
|
 |
« Reply #6 on: 17 May '02 - 20:59 » |
Quote
|
OK. So if you eg. put in a 40% reduction on the outputlevel and let every peak be "normalized" after that, that would work wouldn't it?! Do you have an example of a gain controll.. The silent part is no problem for me, because the system is based on a crossfading system and just techno songs is usally played... I just wanne se some example code of such a solution... But is there another word for "getting the same output gain" on every song... Is it smart using the "compressor" built in the DirectX system and then get the "same" effect?! Please help me out here... Discussing if it is normalizing or not is not the issue here. The issue is getting this f*** thing to give the same output on the songs... 
|
|
|
|
|
Logged
|
|
|
|
|
Ian @ un4seen
Administrator
Posts: 15276
|
 |
« Reply #7 on: 18 May '02 - 16:35 » |
Quote
|
Here's a simple dynamic amplification DSP... #define amptarget 30000 // target level #define ampquiet 800 // quiet level #define amprate 0.02f // amp adjustment rate
typedef struct { float gain; // amplification level int delay; // delay before increasing level int count; // count of sequential samples below target level int high; // the highest in that period int quiet; // count of sequential samples below quiet level } AUTOAMPSTUFF;
void CALLBACK autoamp(HDSP handle, DWORD channel, void *buffer, DWORD length, AUTOAMPSTUFF *amp) { short *data=(short*)buffer; DWORD c; for (c=0;c<length/2;c++) { int s=(int)(data[c]*amp->gain); // amplify sample int sa=abs(s); if (abs(data[c])<ampquiet) amp->quiet++; // sample is below quiet level else amp->quiet=0; if (sa<amptarget) { // amplified level is below target if (sa>amp->high) amp->high=sa; amp->count++; if (amp->count==amp->delay) { // been below target for a while if (amp->quiet>amp->delay) // it's quiet, go back towards normal level amp->gain+=10*amprate*(1-amp->gain); else amp->gain+=amprate*amptarget/amp->high; // increase amp amp->high=amp->count=0; // reset counts } } else { // amplified level is above target if (s<-32768) s=-32768; else if (s>32767) s=32767; amp->gain-=2*amprate*sa/amptarget; // decrease amp amp->high=amp->count=0; } data[c]=(short)s; // replace original sample with amplified version } }
...
AUTOAMPSTUFF amp;
amp.gain=1; amp.delay=BASS_ChannelSeconds2Bytes(handle,1)/2; amp.count=amp.high=amp.quiet=0; BASS_ChannelSetDSP(handle,(DSPPROC*)&autoamp,&);
|
|
|
|
|
Logged
|
|
|
|
|
|
|
Largie
Posts: 110
|
 |
« Reply #9 on: 19 May '02 - 16:33 » |
Quote
|
It seems to work real nice on every kind of music I tested...  GREAT IAN!!! But of coz there are some questions... #define amptarget 30000 // target level #define ampquiet 800 // quiet level #define amprate 0.02f // amp adjustment rate The amptarget is that the "output" level you decide here (like 30000 is the highest peak where you reduce the output signal?) And quiet is like the "lowest" level that should not be gained... So if you use this on for example orchestra music it will not "overgain" the quiet parts of it?!  And then the amprate is the steps between the gains so if it was to low the last time you add the amprate or if it was to high you reduce with the amprate. Is this the right thinking of how this dynamic DSP output filter work?!  (I guess I'll have to buy a math and DSP filter book after this, because this is cool!!!!)
|
|
|
|
|
Logged
|
|
|
|
|
Ian @ un4seen
Administrator
Posts: 15276
|
 |
« Reply #10 on: 20 May '02 - 13:38 » |
Quote
|
The amptarget is that the "output" level you decide here (like 30000 is the highest peak where you reduce the output signal?) Yep, it's the target level... you don't want to reduce it too much, otherwise you reduce the music's dynamics (there's a smaller range of levels for each sample). Better to reduce the channel volume, if you want a lower output level. And quiet is like the "lowest" level that should not be gained... So if you use this on for example orchestra music it will not "overgain" the quiet parts of it?!  Below the "quiet" level, it actually reduces the amplification instead of increasing it... did that for gaps between tracks (eg. when streaming), so that the next track does not start with ear pain  It seems to work quite well as it is, but it was hacked together in a few mins, so it can probably be fine-tuned some 
|
|
|
|
|
Logged
|
|
|
|
|
FormulaV8
Posts: 47
|
 |
« Reply #11 on: 20 May '02 - 18:20 » |
Quote
|
Can someone convert Ians code to VB? 
|
|
|
|
|
Logged
|
|
|
|
|
Largie
Posts: 110
|
 |
« Reply #12 on: 20 May '02 - 22:24 » |
Quote
|
It seems to work quite well as it is, but it was hacked together in a few mins, so it can probably be fine-tuned some   I guess it can... The thing that would be real cool to add, is a compression. (Then it is much easier to get the same soundpicture of different kinds of songs) I guess you know what I compression is. But I tell i anyway. It is like a 3 part band low/mid/high dynamic volume controller. So you can actually boost the base and lower the mid on every stream dynamicly. Meaning that if you play techno songs you'll get more power to the bassdrums. And if you switch the music into eg disco tunes you still will get the same punch if any on the same gain level. It is what AudioStocker calls compression to FM output. Meaning strong base and lower mid and high treble. This should be added to the great dynamic volume controller. Ian: Which books are the best for learning DSP. Programming filters, creating generators and so on?!  Please help me out here so I can start learning... 
|
|
|
|
|
Logged
|
|
|
|
|
|
|
paddy
Posts: 142
|
 |
« Reply #14 on: 23 Jun '02 - 12:14 » |
Quote
|
Jobnik, How about adding a compressor to bassFX? It would also be nice to provide a bandwidth parameter to the dsp EQ.
Rgds.
|
|
|
|
|
Logged
|
|
|
|
|
(: JOBnik! :)
Posts: 984
|
 |
« Reply #15 on: 24 Jun '02 - 01:38 » |
Quote
|
Hi  Jobnik, How about adding a compressor to bassFX? It would also be nice to provide a bandwidth parameter to the dsp EQ.
* Sorry no Compressor yet. * I've updated the EQ, so now it's using the BiQuad algorithm, and there's a Bandwidth parameter added too  I'll send the updated .DLL to Ian when I'll finish all optimizations. Have fun!  JOBnik! 
|
|
|
|
|
Logged
|
|
|
|
|
paddy
Posts: 142
|
 |
« Reply #16 on: 25 Jun '02 - 11:58 » |
Quote
|
I just got an unhandled exception at bass_fx when using DSP. I'm not sure what caused it - my app was just playing fine then suddenly it crashes! There could also be a bit of distortion (clicks) when adjusting the EQ at low frequencies eg 80-100. Guess I wouldnt mind trying out the new EQ code.  Cheers!
|
|
|
|
« Last Edit: 25 Jun '02 - 12:00 by paddy »
|
Logged
|
|
|
|
|
paddy
Posts: 142
|
 |
« Reply #17 on: 25 Jun '02 - 12:39 » |
Quote
|
The bass_fx Error occurred again! This is the info i got from the C++ Debugger: 01E823A0 C2 10 00 ret 10h 01E823A3 55 push ebp 01E823A4 8B EC mov ebp,esp 01E823A6 83 7D 0C 00 cmp dword ptr [ebp+0Ch],0 01E823AA 56 push esi 01E823AB 57 push edi 01E823AC 8B 7D 08 mov edi,dword ptr [ebp+8] 01E823AF 8B F1 mov esi,ecx 01E823B1 0F 84 B6 00 00 00 je 01E8246D 01E823B7 53 push ebx 01E823B8 8D 5E 14 lea ebx,[esi+14h] 01E823BB 0F BF 07 movsx eax,word ptr [edi]
Error Occurs at the last line - ie 01E823BB 0F BF 07 movsx eax,word ptr [edi]
The error message is: Unhandled exception in bass_fx.dll:0xc0000005: Access Violation
Any idea as to what might have caused it? Rgds.
|
|
|
|
|
Logged
|
|
|
|
|
(: JOBnik! :)
Posts: 984
|
 |
« Reply #18 on: 25 Jun '02 - 14:54 » |
Quote
|
Hi  hmmm.... Does the Error occur when you're using Reverb/Echo? Or with any other effect? Does it occur in Compiled/Non Compiled modes? It seemed to be a Memory error... I'll check it out  btw, could you please write a msg in BASS_FX section?  Have fun!  JOBnik! 
|
|
|
|
« Last Edit: 25 Jun '02 - 19:27 by JOBnik »
|
Logged
|
|
|
|
|
paddy
Posts: 142
|
 |
« Reply #19 on: 27 Jun '02 - 08:50 » |
Quote
|
Does the Error occur when you're using Reverb/Echo? Or with any other effect?
I only use DSP EQ. Does it occur in Compiled/Non Compiled modes?
Compiled. It seemed to be a Memory error...
Could be. But I have 128MB Ram and lots of HDD space... I've been trying out VB DSP callbacks in another separate app and it seems that bugs manifest themselves as memory problems (eg when dealing with Byval (pointers?) variables. Eg. Floating-Point Inexact Result Exceptions... I'm slowly starting to get the hang of this DSP Call back thing - but I know I still kave a long way to go. Rgds.
|
|
|
|
|
Logged
|
|
|
|
|