Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio Quality issues #3

Open
marcenglish opened this issue Oct 22, 2017 · 5 comments
Open

Audio Quality issues #3

marcenglish opened this issue Oct 22, 2017 · 5 comments

Comments

@marcenglish
Copy link

The code and wav files provided work, but the output is pretty heavily distorted/clipping.

I trimmed the output level one of the wav files, and that seemed to fix the sound issue, though not consistently. I've tried playing with the buffer size and trigger timing, but I cannot get the audio to play cleanly on a consistent basis. Have you experienced any such issues with your build?

Thanks

@romaca
Copy link

romaca commented Nov 19, 2017

I have had some success with this code but have discovered a few interesting issues which may help:
I'm hooking up the MAX98357A (adafruit breakout) similar to the one used in the demo I believe.
I've studied the waveforms of the BCLK, LRCLK and DIN and have found two problems:-

  1. The data is left justified (an allowed variant of the spec) but won't work properly with the MAX98357A. It would with the MAX98357B. However by shifting the data stream on the fly 1 bit to the right before writing to the FIFO buffers brings the data back into spec and I can get a pure 1000Hz test tone I'm experimenting with most of time.
  2. I have noticed a second problem with the i2s bit stream. The BCLK changes phase now and again relative to the LRCLK. If you look at the I2S spec the LRCLK changes state with the falling edge of BCLK. When this happens the sound is great as it's compliant. If the LRCLK changes state on the rising edge of BCLK the sound is, not surprisingly, crap.
    The second problem I am now trying to fix but is probably a driver issue. If anyone in the meantime can shed some light on this instability ; how LRCLK and BCLK can be kept in sync this would great.

Here's my play loop:-

#define SLC_BUF_LEN (64) // Use the same buffer size as DMA

int playWaveFile(wavFILE_t *wavFile,wavProperties_t props){
static uint8_t readBuffer[SLC_BUF_LEN
2]; // DMA uses 32bits (only mono therefore 16 bits) / reads from SPIFFS in bytes
static uint16_t *p = (uint16_t *)readBuffer;
int count;

i2s_begin();
i2s_set_rate(props->sampleRate);
//Serial.println(props->sampleRate);
int bShiftIn= 0;
int bShiftOut = 0;

// Note: 8266 little endian - wav file little endian - should be good

while((count = wavRead(wavFile,readBuffer, SLC_BUF_LEN*2))  > 0) {
    //Serial.print("Bytes transferred "); Serial.println(accumulated_count);
    count >>=1;
    for(p=(uint16_t *)readBuffer;count;count--,p++) {
        // Shift output data 1 bit to the right to conform to I2S (non left justified) as
        // hardware outputs data left justified.
        bShiftOut = *p & 0x0001;
        *p = (*p>>1 & 0x7fff) | (bShiftIn<<15);
        bShiftIn = bShiftOut;
        //Serial.println(String(*p,HEX));
        i2s_write_lr(*p,*p); //left channel data = right channel (mono) -  blocks when full - DMA's in background
    }
    //Serial.print("*");
    yield();
}
i2s_end();

}

@dagnall53
Copy link

@romaca Thanks for your inputs.. I have solved my crashes, (see my recent issue post in ( https://github.com/techman83/esp8266-wavplay )
I would now would like to improve sound quality, but I cannot see exactly where your "play loop" modification fits in the code ?
Can you be more explicit about which file and function your code corrects?
many thanks
dagnall

@timum-viw
Copy link

Thanks a lot @romaca ! Shifting the stream greatly improves sound quality. Did you have any luck with the other issue you mentioned?

@romaca
Copy link

romaca commented Dec 20, 2017

@timum-viw - sorry I haven’t persued the clock instability issue. Espressif’s ESP8266 interface documentation is very brief (intentionally?) so to fully understand them one needs to read the core driver code which is a pain. Since Earle Philhower’s code works (I have it working), if I have time I’ll try and locate the differences. I suspect it has to do with touching the sampling clock register at the wrong time.

@Teddyz
Copy link

Teddyz commented Jan 12, 2018

Looks to me that the variable sample should be an uint32_t. Can this be part of the audio trouble?

bool ICACHE_FLASH_ATTR i2s_write_lr_nb(int16_t left, int16_t right){
  int sample = right & 0xFFFF;
  sample = sample << 16;
  sample |= left & 0xFFFF;
  return i2s_write_sample_nb(sample);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants