This topic was moved from Q&A.
Hello All,Is it possible to avoid clicks during DSD playback?I mean the clicks at the beginning and at the end of playback (so PCM->DSD and DSD-PCM transition).Clicks are presents as in DoP, as also in Native mode.I've tried to use mute line, to short the DAC's output to ground, but click appeared before the mute is activsted, so this did not help.Thank you. Read
USB Audio Reference Design - click in DSD
-
- XCore Addict
- Posts: 150
- Joined: Sun Feb 23, 2014 11:30 am
-
- XCore Addict
- Posts: 150
- Joined: Sun Feb 23, 2014 11:30 am
infiniteimprobability wrote:
It can be done, but it needs a little thought and work.
Native DSD is easier becasue the host signals a change in interface (USB interface) which allows the firmware to identify stream start/stop. This means mute code can be applied when changing modes outside of streaming. There should be hooks for this alread (UserAudioStreamStart/UserAudioStreamStop)
DoP is trickier. Of course DoP is transported as a PCM stream. It's only at the I2S driver layer that the DoP markers are detected. When 32 consequtive markers are detected, then I2S changes the DAC mode and starts extracting and transferring DSD to the DAC. This means track or stream starts of DoP will always have 32 PCM samples followed by PCM to DSD mode change. You may also get a pop at the end, especially if the host decides to stream 0s after playing the track, which of course are not DoP samples.
The key is to assert hardware mute before any mode changes happen. This can be done in the following code at the point where dsdMode = ... is executed.
Ultimately, this will all depend on your hardware (how well/quickly it can assert mute) and where you apply the mute code. If you do not have mute hardware it is harder. It can be done, but I know that certain DACs (eg. ESS) are a lot easier to make behave quietly on mode changes than others.
It can be done, but it needs a little thought and work.
Native DSD is easier becasue the host signals a change in interface (USB interface) which allows the firmware to identify stream start/stop. This means mute code can be applied when changing modes outside of streaming. There should be hooks for this alread (UserAudioStreamStart/UserAudioStreamStop)
DoP is trickier. Of course DoP is transported as a PCM stream. It's only at the I2S driver layer that the DoP markers are detected. When 32 consequtive markers are detected, then I2S changes the DAC mode and starts extracting and transferring DSD to the DAC. This means track or stream starts of DoP will always have 32 PCM samples followed by PCM to DSD mode change. You may also get a pop at the end, especially if the host decides to stream 0s after playing the track, which of course are not DoP samples.
The key is to assert hardware mute before any mode changes happen. This can be done in the following code at the point where dsdMode = ... is executed.
Ultimately, this will all depend on your hardware (how well/quickly it can assert mute) and where you apply the mute code. If you do not have mute hardware it is harder. It can be done, but I know that certain DACs (eg. ESS) are a lot easier to make behave quietly on mode changes than others.
Code: Select all
#if (DSD_CHANS_DAC != 0) && (NUM_USB_CHAN_OUT > 0)
/* Check for DSD - note we only move into DoP mode if valid DoP Freq */
/* Currently we only check on channel 0 - we get all 0's on channels without data */
if((dsdMode == DSD_MODE_OFF) && (curSamFreq > 96000))
{
if((DSD_MASK(samplesOut[0]) == dsdMarker) && (DSD_MASK(samplesOut[1]) == dsdMarker))
{
dsdCount++;
dsdMarker ^= DSD_MARKER_XOR;
if(dsdCount == DSD_EN_THRESH)
{
dsdMode = DSD_MODE_DOP;
dsdCount = 0;
dsdMarker = DSD_MARKER_2;
// Set clocks low
p_lrclk <: 0;
p_bclk <: 0;
p_dsd_clk <: 0;
return 0;
}
}
else
{
dsdCount = 0;
dsdMarker = DSD_MARKER_2;
}
}
else if(dsdMode == DSD_MODE_DOP) // DSD DoP Mode
{
/* If we are running in DOP mode, check if we need to come out */
if((DSD_MASK(samplesOut[0]) != DSD_MARKER_1) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_1))
{
if((DSD_MASK(samplesOut[0]) != DSD_MARKER_2) && (DSD_MASK(samplesOut[1]) != DSD_MARKER_2))
{
dsdMode = DSD_MODE_OFF;
// Set clocks low
p_lrclk <: 0;
p_bclk <: 0;
p_dsd_clk <: 0;
return 0;
}
}
}
#endif
Last edited by AlexAdvice on Mon Mar 30, 2015 9:54 am, edited 1 time in total.
-
- XCore Addict
- Posts: 150
- Joined: Sun Feb 23, 2014 11:30 am
Then I wrote:
Thank you for the reply.
I'm making the "mute" at audiostream.xc:
also at audiohw.xc I make:
But I get a huge click at the beginning and at the end of DSD playback.
Thank you for the reply.
I'm making the "mute" at audiostream.xc:
Code: Select all
void UserAudioStreamStart(void)
{
MuteAudio(0);
}
void UserAudioStreamStop(void)
{
MuteAudio(1);
}
also at audiohw.xc I make:
Code: Select all
void AudioHwConfig(unsigned samFreq, unsigned mClk, chanend ?c_codec, unsigned dsdMode,
unsigned samRes_DAC, unsigned samRes_ADC)
{
timer t;
unsigned time;
unsigned tmp;
unsigned freq;
/* Put codec in reset and set master clock select appropriately */
/* Read current port output */
PORT32A_PEEK(tmp);
tmp &= (~ ( P32A_F0 | P32A_F1)); // clear these bits
MuteAudio(1);
if(dsdMode!=DSD_MODE_OFF){ // DSD Mode -------------------------------------------------------------------------
DSD_PIN <: DSD_ON;
if(dsdMode == DSD_MODE_NATIVE){
tmp |=P32A_F1; // Native Mode
if (samFreq > 6000000) tmp |=P32A_F0; // // DSD128
}else{
if (samFreq > 3000000) tmp |=P32A_F0; // > 3MHz e.g. 2.2822400 MHz */) // DSD128
}
}else{// PCM Mode -------------------------------------------------------------------------
DSD_PIN <:DSD_OFF;
if ((samFreq % 22050) == 0){/* Frequency select low for 441000 etc */
tmp &= (~P32A_CLK_SEL);
freq= samFreq /44100;
}else{ //if((samFreq % 24000) == 0) /* Frequency select high for 48000 etc */
tmp |= P32A_CLK_SEL;
freq= samFreq /48000;
}
PORT32A_OUT(tmp);
/* Hold in reset for MIN_RESET_TIME */
t :> time;
time += MIN_RESET_TIME;
t when timerafter(time) :> int _;
if(dsdMode!=DSD_MODE_OFF){ // tmp: For DSD set Mute Off here, for PCM - at UserAudioStreamStart() in audiostream.xc
MuteAudio(0);
}
}
Last edited by AlexAdvice on Mon Mar 30, 2015 9:55 am, edited 1 time in total.
-
- XCore Addict
- Posts: 150
- Joined: Sun Feb 23, 2014 11:30 am
infiniteimprobability wrote:
"But I get a huge click at the beginning and at the end of DSD playback."
Can you sepearte out DSD native and DoP and say what happens on each? The handling for these is very different as mentioned.
The UserAudioStreamStart and UserAudioStreamStop functions are called directly from EP0 as soon as the interface changes which is the first notice that the firmware gets of incoming DSD native streaming. What you have shown should help with DSD native - you will need to make the other changes into audio.xc to handled DoP better.
Havce you looked on a scope to see what happens with the DAC output vs. mute line? That could be quite helpful
Finally, it may be worth moving this to a thread - I think the Q&A format is a bit limiting for this level of discussion..
"But I get a huge click at the beginning and at the end of DSD playback."
Can you sepearte out DSD native and DoP and say what happens on each? The handling for these is very different as mentioned.
The UserAudioStreamStart and UserAudioStreamStop functions are called directly from EP0 as soon as the interface changes which is the first notice that the firmware gets of incoming DSD native streaming. What you have shown should help with DSD native - you will need to make the other changes into audio.xc to handled DoP better.
Havce you looked on a scope to see what happens with the DAC output vs. mute line? That could be quite helpful
Finally, it may be worth moving this to a thread - I think the Q&A format is a bit limiting for this level of discussion..
-
- XCore Addict
- Posts: 150
- Joined: Sun Feb 23, 2014 11:30 am
Hello,infiniteimprobability wrote:
Can you sepearte out DSD native and DoP and say what happens on each? The handling for these is very different as mentioned
...
Havce you looked on a scope to see what happens with the DAC output vs. mute line? That could be quite helpful
I'm in a buisiness trip for 2 weeks, I can check these when I'll return.
-
- XCore Addict
- Posts: 150
- Joined: Sun Feb 23, 2014 11:30 am
When the Mute signal is changed, I have huge 1-1.2ms spike at the output.
This happens at PCM->DSD and DSD->PCM transitions in Native DSD Mode.
In DoP mode - the same, plus during positioning on the DSD-file.
Solution maybe is to make 2ms delay of the I2S/DSD-bus signals.
I just answer in Q&A for the similar question:
[quote]
Hi,
I think you need to delay the outputs for 2ms using FIFO in XMOS firmware, but how to do this I don't know.
For DoP maybe it possible to make 2 checks of markers - one before FIFO, one after. The first will switch the control signals (Mute, DSP/PCM), and the second will actualy change the bus output (LRCLK->DSD), as now.
If you will do this, please share you solution, because I'm also want to avoid this pops in my design.
[/quote
This happens at PCM->DSD and DSD->PCM transitions in Native DSD Mode.
In DoP mode - the same, plus during positioning on the DSD-file.
Solution maybe is to make 2ms delay of the I2S/DSD-bus signals.
I just answer in Q&A for the similar question:
[quote]
Hi,
I think you need to delay the outputs for 2ms using FIFO in XMOS firmware, but how to do this I don't know.
For DoP maybe it possible to make 2 checks of markers - one before FIFO, one after. The first will switch the control signals (Mute, DSP/PCM), and the second will actualy change the bus output (LRCLK->DSD), as now.
If you will do this, please share you solution, because I'm also want to avoid this pops in my design.
[/quote
-
- Member++
- Posts: 19
- Joined: Fri Jun 13, 2014 1:35 pm
Hello friends,
did you solved the pops at PCM-DSD-PCM transitions?
did you solved the pops at PCM-DSD-PCM transitions?