2011-04-19 5 views
4

바이트 배열로 저장된 pcm 오디오가 있습니다. 그것은 샘플 당 16 비트입니다. 나는 샘플 오디오 당 8 비트로 만들고 싶다.16 비트 pcm을 8 비트로 변환하십시오.

누구든지 좋은 알고리즘을 제안 할 수 있습니까?

알고리즘에 중요하지 않다고 생각하여 비트율을 언급하지 않았습니다. 맞습니까?

+1

비트 전송률은 중요 할 수 있지만 반드시 그런 것은 아닙니다. A/D 변환기 (오디오를 처리 할 때 최종적으로 A/D를 통해 출력 할 때)를 사용하면 샘플 속도를 65k 배로 높일 수 있습니다 (올바르게 계산 된 경우). 따라서 오버 샘플링). – flolo

+1

자바가 아니지만 ffmpeg가 어떻게 구현되는지 살펴보십시오. http://ffmpeg.org/doxygen/0.5/pcm_8c-source.html – Aleadam

+0

@gosho_ot_pochivka 16 비트 pcm을 24 비트로 변환하는 방법을 알려주십시오. 감사합니다 – ravi

답변

7

왜 지금은 상위 바이트를 가져 오는 것만으로는 충분하지 않은지, 즉 각 샘플의 하위 8 비트를 버리는 것이 보이지 않습니다.

물론 샘플은 선형이라고 가정합니다. 그렇지 않다면 비트를 없애기 전에 선형화하기 위해 무언가를해야 할 수도 있습니다.

eightBit += eightBit < 0xff && ((sixteenBit & 0xff) > 0x80); 

테스트 : 코멘트에 AShelly에 의해 제안

short sixteenBit = 0xfeed; 
byte eightBit = sixteenBit >> 8; 
// eightBit is now 0xfe. 

것은, 반올림 좋은 생각, 즉 우리가 폐기하고있는 바이트가 높은 절반 이상이 최대 인 경우 1을 추가 할 수 있습니다 against 0xff는 클램핑을 구현하므로 0xff에 1을 더하고 위험을 0x00으로 줄이는 위험을 감수하지 않습니다.

+1

잘라 내기 대신 둥근 싶을 수도 있습니다. 'eightbit + = (16 비트 및 0x80) >> 7;'을 추가하십시오. 하위 바이트가 범위의 절반보다 클 경우 1을 더합니다. – AShelly

+1

@AShelly : true, 좋은 생각 일 수 있습니다. 코드에서 0xff00에서 0xffff 범위의 값이 0x00으로 랩되지만 이는 전혀 반올림하지 않는 것보다 나을 것입니다. 내가 편집 할게. 덕분에 – unwind

+0

. 입력이 바이트 배열 (byte [] arr short가 아님) 인 경우 바이트의 절반 즉 arr [0], arr [2], arr [4] 등을 가져 오는 것을 의미합니까? –

1

16 비트 샘플을 표준화 한 다음 8 비트 샘플의 최대 값으로 다시 스케일합니다.

이렇게하면 각 샘플의 하위 8 비트가 삭제되지 않으므로보다 정확한 변환을 얻을 수 있습니다. 그러나 내 솔루션은 선택한 대답보다 계산 상으로 많은 비용이 듭니다.

6

일반적으로 16 비트 샘플이 서명되며 8 비트 샘플은 일반적으로 부호가 없으므로 가장 간단한 대답은 부호가있는 16 비트 샘플을 변환해야한다는 것입니다 (16 비트 샘플은 거의 항상 범위로 저장 됨). -32768에서 +32767까지)를 부호없는 값으로 설정 한 다음 결과의 상위 8 비트를 취합니다. C에서 이것은 output = (unsigned char) ((unsigned short) (input + 32768) >> 8)로 표현 될 수 있습니다. 이것은 좋은 시작이고, 당신의 필요에 충분히 좋을지 모르나, 아주 좋게 들리지는 않을 것입니다. "양자화 잡음"때문에 거칠게 들립니다.

양자화 노이즈는 원래 입력과 알고리즘 출력 간의 차이입니다. 당신이하는 일에 상관없이, 당신은 소음을 갖게 될 것이고, 소음은 평균적으로 "절반"이 될 것입니다. 그것에 대해 할 수있는 것은 없지만 잡음을 덜 눈에 띄게 할 수있는 방법이 있습니다.

양자화 노이즈의 주요 문제점은 패턴을 형성하는 경향이 있다는 것입니다. 입력과 출력의 차이가 완전히 무작위 인 경우 실제로는 문제가 없지만 출력은 반복적으로 파형의 특정 부분에는 너무 높고 다음 부분에는 너무 낮습니다. 귀가이 패턴을 선택합니다.

소리가 좋은 결과를 얻으려면 디더링을 추가해야합니다. 디더링은 양자화 노이즈를 부드럽게하는 기술입니다. 가장 단순한 디더링은 노이즈 패턴을 실제 신호 패턴에서 벗어나지 않도록 노이즈에서 패턴을 제거합니다. 더 나은 디더링은 한 걸음 더 나아가 여러 샘플의 오류 값을 합친 다음 총 오류가 보정 할만큼 충분히 커지면 보정을 추가하여 잡음을 줄이기위한 조치를 취할 수 있습니다.

온라인에서 다양한 디더링 알고리즘에 대한 설명과 코드 샘플을 찾을 수 있습니다. 조사 할 좋은 영역 중 하나는 SoX 도구 http://en.wikipedia.org/wiki/SoX입니다. 소스의 디더링 효과를 확인하고 디더링이 활성화 된 상태와 디더링이 활성화 된 상태에서 다양한 사운드를 16 비트에서 8 비트로 변환하는 실험을하십시오. 8 비트 사운드로 변환 할 때 디더링이 낼 수있는 품질의 차이에 놀랄 것입니다.

1
byteData = (byte) (((shortData +32768)>>8)& 0xFF) 

이것은 나를 위해 일했습니다.

관련 문제