ESP32로 블루투스 오디오 스피커 프로젝트를 개발하게 되었다. ESP32는 아두이노와 IDF, ADF 등 개발하기 편한 여러 가지 플랫폼을 제공하고 있고 많은 예제가 있어 예제만 응용해도 제품화할 아이템들이 다양하다.

게다가 내부램,플래쉬도 괜찮은 용량인데 외부램과 플래쉬용량이 메가 단위로 선택이 가능하다. 또 와이파이/블루투스도 되면서 저렴한 가격이 장점이나..

 

하지만 싼 게 비지떡이란 단점도..

 

블루투스 A2DP를 이용해서 스마트폰의 음원을 재생하는 블루투스 스피커를 개발했는데 의외로 잘 동작해서 Microchip 제품으로 개발할 때보다는 개발이 수월했다. 다만…

간헐적으로 음원 재생 중 음원이 끊이는 (몇 ms?) 동작이 발생했다. 해당 음원 위치로 이동해도 증상은 구현되지 않고, 발생하는 시간, 주기도 랜덤이었다. 내부 롬에 저장한 음원 파일은 정상인데 블루투스로 재생하면 나오니 미치고 팔짝 뛸 노릇이었다.

원인이 무얼까 하고 리스트 업을 해보았다.

  • i2s 전송 완료 인터럽트가 불안전?
  • resample 연산 오류로 인한 노이즈?
  • freertos가 간헐적으로 멈춤 증상을?
  • SPI 통신으로 이루어진 RAM, ROM의 속도 이슈?
  • ESP32의 블루투스 버그 및 단품 문제? 등등..

별별 이유가 머릿속에서 떠올랐다. 하나씩 처리해가면서 원인을 찾아보았다.

i2s 전송 완료 인터럽트가 불안전?

ESP32 I2S로 오디오 전송 시, DMA를 이용해서 전송 완료 인터럽트가 발생하면 큐에 있는 다음 데이터를 바로 전송한다. 캐시 등의 문제나 이 처리 루틴의 문제가 있었다면 내부 음원도 똑같이 나왔을 테니 이건 패스.

resample 연산 오류로 인한 노이즈?

기본 44.1Khz에서 48Khz 이상으로 리 샘플링을 하고 있었다. 리 샘플링 연산도 간단한 공식을 쓰면 특정 음원에서 노이즈가 발생된다. 하지만 그 경우는 같은 음원의 같은 위치에서 발생하는데 이번 프로젝트는 랜덤하게 발생하기에 패스.

ESP32의 블루투스 버그 및 단품 문제?

다른 칩으로 해도 똑같고 만약 블루투스 스택 버그라 하면 나 말고 다른 유저들도 발견했을 텐데 말이 없네.. 이건 최악의 원인이니 패스.

SPI 통신으로 이루어진 RAM, ROM의 속도 이슈?

주요 버퍼위치를 외부램에서 내부램으로 한다 해도 ROM까지는 못 바꾸니.. 이는 추후 다시 검증.

마지막 남은 건, freertos 간헐적 멈춤 증상.

이를 증명해야 하는데 어떻게 증명을 해야 할까 이전 이슈인 ROM 건과같이 보려면 수치화된 데이터가 필요했다. 우선 저 위의 이슈 2개가 원인이어서 블루투스 처리를 유연하게 못한다면, 링버퍼를 추가해 보는 게 어떨까 생각이 들었다.

출처: 링크

 

버퍼를 만들어서 i2s 오디오 데이터를 채우다가 반 이상 채워지면 i2s 전송을 하도록 해보면서 버퍼의 남은 용량을 측정하니 재미있는 결과가 나왔다.

링버퍼 사용량 측정

그래프를 보면 처음 쭉 오디오가 축적되다가 데이터 사용과 축적이 반복되고 있다.( 그래프의 빨간 선이 데이터 push, 노란 선이 pop)

20K 정도의 데이터 폭으로 안정적으로 I2S 오디오 데이터가 사용되는데, 간헐적으로 블루투스 프로세스가 hang이 걸렸는지 데이터 push와 pop이 제대로 안되는 구간이 발생한다.

30K정도의 폭 발생

주기적으로 비슷한 크기의 데이터 축적 및 사용이 기록되다가 가끔씩 데이터 축적이 안되는 상황이 나타났다.

리 샘플링의 딜레이인지 freertos 구동 중의 hang 인지 원인은 모르지만 간헐적으로 일정 않게 딜레이가 발생한다는 게 증명됐다.

 

다행히도 버퍼를 적용한 게 잘 맞아 들었는지 멈칫하던 증상이 사라졌다.

오디오 개발이라는 게 생각보다 신경 쓸게 많다는 걸 느낀 하루였다.