|
get sample instance actual amplitude (volume) |
wootrop
Member #14,516
August 2012
|
hello! i'm new in the fantastic world of allegro! For exercise, i'm making a little sample player (like a keyboard drum). I'd like to show each sample volume intensity with a rectangle that modify his height with the amplitude of the sample. Like a real time v-meter of the sample. There is some function (al_get_sample_instance_amplitude?) that return with the volume of the sample? (not the gain) Thank you so much!! I will really appreciate your help! |
SiegeLord
Member #7,827
October 2006
|
Use al_get_sample_data to get at the actual waveform (use al_get_sample_instance_position to see where it is playing currently and al_get_sample_depth and al_get_sample_channels to see what format the waveform data is in). "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
wootrop
Member #14,516
August 2012
|
thank you SiegeLord!!! But i can't make it work! Can you show me an example? thank you so much! |
SiegeLord
Member #7,827
October 2006
|
Here's a sample program. To get the volume it computes the root mean square over several milliseconds. You'll want to actually implement the get_wave_power function to handle various audio formats and channel numbers. I've attached a test sound that the code works on. 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_audio.h>
3#include <allegro5/allegro_acodec.h>
4#include <math.h>
5#include <stdio.h>
6
7float get_wave_power(ALLEGRO_SAMPLE* spl, unsigned int pos)
8{
9 /* Handle more formats and channels */
10 assert(al_get_sample_depth(spl) == ALLEGRO_AUDIO_DEPTH_INT16);
11 assert(al_get_sample_channels(spl) == ALLEGRO_CHANNEL_CONF_1);
12 return float(((short*)al_get_sample_data(spl))[pos]) / 32767.0f;
13}
14
15int main()
16{
17 al_init();
18 al_install_audio();
19 al_reserve_samples(1);
20 al_init_acodec_addon();
21
22 ALLEGRO_SAMPLE* sample = al_load_sample("test.ogg");
23 assert(sample);
24 ALLEGRO_SAMPLE_INSTANCE* inst = al_create_sample_instance(sample);
25 al_attach_sample_instance_to_mixer(inst, al_get_default_mixer());
26 al_play_sample_instance(inst);
27
28 while(al_get_sample_instance_playing(inst))
29 {
30 al_rest(0.1);
31 unsigned int pos = al_get_sample_instance_position(inst);
32 float rms = 0;
33 const float seconds_to_average = 0.05f;
34 const int samples_to_average = (int)(al_get_sample_frequency(sample) * seconds_to_average);
35 unsigned int start;
36 if(pos < samples_to_average)
37 start = 0;
38 else
39 start = pos - samples_to_average;
40
41 for(unsigned int ii = start; ii < pos; ii++)
42 {
43 float power = get_wave_power(sample, ii);
44 rms += power * power;
45 }
46 rms = sqrt(rms / (pos - start));
47 printf("Volume: %d%%\n", (int)(100 * rms));
48 }
49
50 return 0;
51}
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
wootrop
Member #14,516
August 2012
|
Great!!! Now i'm not at home but i will try the code when possible and then i will inform you! |
Dizzy Egg
Member #10,824
March 2009
|
Nice one!
---------------------------------------------------- |
wootrop
Member #14,516
August 2012
|
Wow very good!!!! you must implement this function to allegro library! one question, what is the formula that you used? (What is the 32767.0f number?) thank you SiegeLord!! i will post my exercise code when i've implemented a general formula for this! |
SiegeLord
Member #7,827
October 2006
|
wootrop said: What is the 32767.0f number? It's implied by ALLEGRO_AUDIO_DEPTH_INT16. Look at ALLEGRO_AUDIO_DEPTH. Here's a link for RMS: http://en.wikipedia.org/wiki/Root_mean_square . I used RMS since it seemed a reasonable thing to use as a proxy to volume. In a real application it's also probably best to high pass filter the data before computing the RMS so you don't get a positive RMS for non-zero silence. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
wootrop
Member #14,516
August 2012
|
There are some issues in Allegro 5.0.7 audio functions i think: Info source: Adobe Audition Info source: Allegro 5.0.7 -------------------------------------- Info source: Adobe Audition Info source: Allegro 5.0.7 IDLE: Codeblocks 10.05 EDIT 1float get_sample_amplitude (ALLEGRO_SAMPLE *sample, int position)
2{
3 // Return a float value from 0 to 1.
4 short *spl_data = (short*)al_get_sample_data(sample);
5 return float(sqrt(pow(spl_data[position], 2))/32768.0f);
6}
Use: So this is my demo: {"name":"spep.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/d\/cdc3f9e5d9d16d5562484104d0703d71.jpg","w":1366,"h":768,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/d\/cdc3f9e5d9d16d5562484104d0703d71"} |
SiegeLord
Member #7,827
October 2006
|
wootrop said: al_get_sample_channels: 32(?) Read the docs for those functions. They don't return values whose numerical interpretation is meaningful. Also... "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
wootrop
Member #14,516
August 2012
|
Ok, so i will read the documentation! SiegeLord said: sqrt(pow(spl_data[position], 2)) is exactly equal to just spl_data[position]. Isn't the same thing, because i get a positive value with the pow, and then i make a square root to get back the original value. Result: absolute value. (i've just now discovered the abs function ) so this is more correct: 1float get_sample_peak (ALLEGRO_SAMPLE *sample, int position)
2{
3 // Return a float value from 0 to 1.
4 short *spl_data = (short*)al_get_sample_data(sample);
5 return float(abs(spl_data[position])/32768.0f);
6}
EDIT Sorry I have another question... Why my program compiled with Codeblocks and Mingw take up more space (about 500kb) and compiled with VC2010 is only about 100kb? (are both dinamic linked) Codeblocks Release settings: liballegro-5.0.7-monolith-mt.a (to the linker) and -s (Strip all symbols from binary (minimizes size)) and -O3 (Optimize fully (for speed)) Visual Studio 2010 Release settings: allegro-5.0.7-monolith-mt.lib (to the linker) and generation code is setted to /MT (multithread). EDIT2 |
|