Dear all
we are preparing for a project with xmos xu216 chip, a frontpanel will be used display audio volume. where can we extract audio volume level meter data? How to get them?
Do volsIn[ ] and volsOut[ ] use to save audio level meter data? Would you please give me some suggestions? thanks in advance!
int AudioClassRequests_2( )
{
/* Feature Units */
case FU_USBOUT:
case FU_USBIN:
/* Inspect Control Selector (CS) */
switch(sp.wValue >> 8)
{
case FU_VOLUME_CONTROL:
if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D)
{
/* Expect OUT here (with volume) */
if((result = XUD_GetBuffer(ep0_out, buffer, datalength)) != XUD_RES_OKAY)
{
return result;
}
if(unitID == FU_USBOUT)
{
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_OUT)
{
volsOut[ sp.wValue&0xff ] = buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
}
}
else
{
if ((sp.wValue & 0xff) <= NUM_USB_CHAN_IN)
{
volsIn[ sp.wValue&0xff ]= buffer[0] | (((int) (signed char) buffer[1]) << 8);
updateVol( unitID, ( sp.wValue & 0xff ), c_mix_ctl );
return XUD_DoSetRequestStatus(ep0_in);
}
}
}
}
how to extract audio volume level meter from audio stream ( PC(host) to Xmos device) ?
-
- Member++
- Posts: 16
- Joined: Thu Nov 10, 2016 2:33 am
-
- XCore Legend
- Posts: 1913
- Joined: Thu Jun 10, 2010 11:43 am
-
- Member++
- Posts: 16
- Joined: Thu Nov 10, 2016 2:33 am
Thanks for you information, mon2
int left = (int)samples_out[0];
int right = (int)samples_out[1];
you mean that samples_out[0] and samples_out[1] are left and right audio volume value. Is it right ?
int left = (int)samples_out[0];
int right = (int)samples_out[1];
you mean that samples_out[0] and samples_out[1] are left and right audio volume value. Is it right ?
-
- Member++
- Posts: 16
- Joined: Thu Nov 10, 2016 2:33 am
one more thing, what means? the following code, thanks!
if (timeafter(t_now, t_trig)){
unsigned mac_h, mac_l;
{mac_h, mac_l} = lmul(left_vu, MUL_PWR_100_DIV_2P32, 0, 0);
left_vu = mac_h;
{mac_h, mac_l} = lmul(right_vu, MUL_PWR_100_DIV_2P32, 0, 0);
right_vu = mac_h;
t_trig = t_now + (DECAY_TIME_UNIT_MS * 1000 * DECAY_TIME_CONSTANT_MS);
}
if (timeafter(t_now, t_trig)){
unsigned mac_h, mac_l;
{mac_h, mac_l} = lmul(left_vu, MUL_PWR_100_DIV_2P32, 0, 0);
left_vu = mac_h;
{mac_h, mac_l} = lmul(right_vu, MUL_PWR_100_DIV_2P32, 0, 0);
right_vu = mac_h;
t_trig = t_now + (DECAY_TIME_UNIT_MS * 1000 * DECAY_TIME_CONSTANT_MS);
}
-
- Member++
- Posts: 16
- Joined: Thu Nov 10, 2016 2:33 am
Anyone else can give more messages about this topic, thanks!
-
- XCore Legend
- Posts: 1126
- Joined: Thu May 27, 2010 10:08 am
which bit is unclear?
When a timer reaches a certain value it calculates the next value of the decayed peak value. The defines are in there to set the rate at which the exponential decay occurs.
Take a look at the place where the defies are (see below). Hopefully this explains it.
The decay is done using the built-in function for the MACS which is the fastest way to do a signed multiply. See xs1.h for the prototype of this.
When a timer reaches a certain value it calculates the next value of the decayed peak value. The defines are in there to set the rate at which the exponential decay occurs.
Take a look at the place where the defies are (see below). Hopefully this explains it.
Code: Select all
#define DECAY_TIME_CONSTANT_MS 300 //How many milliseconds to decay to 0.368
#define MUL_PWR_100_DIV_2P32 4252200097 //Value to multiple by (followed by div 2^32) 100 times
//to get to 0.368 (ie. the time constant). Makes maths easy!
#define DECAY_TIME_UNIT_MS 1 //How often to do the delay calc. Can be anything > longest sample period
-
- Member++
- Posts: 16
- Joined: Thu Nov 10, 2016 2:33 am
Hi infiniteimprobability
Thanks for your reply and messages,
i still have the following puzzled questions, would you please explain them, thanks again!
In README.txt of vu.zip, you wrote :
Finally, in audio.xc in sc_usb_audio, insert the following:
At the top of the file:
#include "vu_calc_inline.h"
At line number ~690, add the function call to VU calculation:
~~~~~~~~~~~~~~~~~~~~~snip~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef CODEC_MASTER /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */
doI2SClocks(divide);
#endif
//Inline the VU calculation algo
vu_calc(samplesOut);
#ifdef
ADAT_TX TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1);
#endif
In other words, samplesOut[0] and samplesOut[1] in audio.xc are used to save audio volume value, Is it right?
what difference between left and left_vu in vu_calc( ) ?
what function is the below code ?
if (timeafter(t_now, t_trig)){
unsigned mac_h, mac_l;
{mac_h, mac_l} = lmul(left_vu, MUL_PWR_100_DIV_2P32, 0, 0);
left_vu = mac_h;
{mac_h, mac_l} = lmul(right_vu, MUL_PWR_100_DIV_2P32, 0, 0);
right_vu = mac_h;
t_trig = t_now + (DECAY_TIME_UNIT_MS * 1000 * DECAY_TIME_CONSTANT_MS);
}
one more thing, when i change windows audio volume, i find volsOut[ sp.wValue&0xff ] in int AudioClassRequests_2( ) will be changed, but volsOut no change while changing player volume, why ?
Thanks for your reply and messages,
i still have the following puzzled questions, would you please explain them, thanks again!
In README.txt of vu.zip, you wrote :
Finally, in audio.xc in sc_usb_audio, insert the following:
At the top of the file:
#include "vu_calc_inline.h"
At line number ~690, add the function call to VU calculation:
~~~~~~~~~~~~~~~~~~~~~snip~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef CODEC_MASTER /* Clock out the LR Clock, the DAC data and Clock in the next sample into ADC */
doI2SClocks(divide);
#endif
//Inline the VU calculation algo
vu_calc(samplesOut);
#ifdef
ADAT_TX TransferAdatTxSamples(c_adat_out, samplesOut, adatSmuxMode, 1);
#endif
In other words, samplesOut[0] and samplesOut[1] in audio.xc are used to save audio volume value, Is it right?
what difference between left and left_vu in vu_calc( ) ?
what function is the below code ?
if (timeafter(t_now, t_trig)){
unsigned mac_h, mac_l;
{mac_h, mac_l} = lmul(left_vu, MUL_PWR_100_DIV_2P32, 0, 0);
left_vu = mac_h;
{mac_h, mac_l} = lmul(right_vu, MUL_PWR_100_DIV_2P32, 0, 0);
right_vu = mac_h;
t_trig = t_now + (DECAY_TIME_UNIT_MS * 1000 * DECAY_TIME_CONSTANT_MS);
}
one more thing, when i change windows audio volume, i find volsOut[ sp.wValue&0xff ] in int AudioClassRequests_2( ) will be changed, but volsOut no change while changing player volume, why ?
-
- XCore Legend
- Posts: 1126
- Joined: Thu May 27, 2010 10:08 am
Code: Select all
In other words, samplesOut[0] and samplesOut[1] in audio.xc are used to save audio volume value, Is it right?
Code: Select all
what difference between left and left_vu in vu_calc( ) ?
Looks like left is only sent to xscope, so it debug only. You may delete it.
Peak hold with decaywhat function is the below code ?
Not sure, but for most cases (where mixer is not enabled) volumes are handled via shared memory variables "multOut" which are picked up in decouple.xc. This is where digital volume control is normally appliedone more thing, when i change windows audio volume, i find volsOut[ sp.wValue&0xff ] in int AudioClassRequests_2( ) will be changed, but volsOut no change while changing player volume, why ?
-
- Member++
- Posts: 16
- Joined: Thu Nov 10, 2016 2:33 am
thanks,infiniteimprobability
where can we get input audio volume data ? is it samplesIn_1[ ] ?
where can we get input audio volume data ? is it samplesIn_1[ ] ?
-
- XCore Legend
- Posts: 1126
- Joined: Thu May 27, 2010 10:08 am
Depends on wether you want the decibel volume value sent by the host or the calculated mutliplier which is used to scale the samples. Take a look in audiorequests.xc in the section that handles the FeatureUnit (volume) control requests:
Code: Select all
case FU_USBOUT:
{
/* Calc multipliers with 29 fractional bits from a db value with 8 fractional bits */
/* 0x8000 is a special value representing -inf (i.e. mute) */
unsigned master_vol = volsOut[0] == 0x8000 ? 0 : db_to_mult(volsOut[0], 8, 29);
unsigned vol = volsOut[channel] == 0x8000 ? 0 : db_to_mult(volsOut[channel], 8, 29);
x = longMul(master_vol, vol, 29) * !mutesOut[0] * !mutesOut[channel];
#ifdef OUT_VOLUME_IN_MIXER
if (!isnull(c_mix_ctl))
{
outuint(c_mix_ctl, SET_MIX_OUT_VOL);
outuint(c_mix_ctl, channel-1);
outuint(c_mix_ctl, x);
outct(c_mix_ctl, XS1_CT_END);
}
#else
asm("stw %0, %1[%2]"::"r"(x),"r"(p_multOut),"r"(channel-1));
#endif
break;
}