ADX(파일 형식)
ADX (file format)이 기사는 대부분의 독자들이 이해하기에는 너무 전문적일 수 있다.(2020년 1월 (이 및 에 대해 ) |
개발자 | CRI 미들웨어 |
---|---|
초기 릴리즈 | 1996 |
플랫폼 | 크로스 플랫폼 |
유형 | 코덱 / 파일 형식 |
면허증. | 독자 사양 |
웹 사이트 | CRI 미들웨어 |
CRI ADX는 CRI Middleware가 비디오 게임에 사용하기 위해 개발한 손실 전용 오디오 스토리지 및 압축 형식입니다. ADPCM에서 파생되었습니다.가장 주목되는 특징은 세가 드림캐스트용 게임뿐만 아니라 플레이스테이션2, 게임큐브, Wii 게임 등 다양한 게임의 백그라운드 사운드에 유용한 것으로 입증된 루프 기능이다.ADX를 최초로 사용한 게임 중 하나는 세가 새턴의 버닝 레인저스였다.특히 드림캐스트 세대부터 적어도 섀도우 더 헤지호그까지의 소닉 더 헤지호그 시리즈는 사운드와 음성 녹음을 위해 이 형식을 사용했다.오리지널 Xbox용 Jet Set Radio Future도 이 [1]형식을 사용했습니다.
ADX 툴킷에는, 메인 ADPCM 인코딩에 가세해 형제 형식인 AHX 와 복수의 CRI ADX 및 AHX 트랙을 1 개의 컨테이너 파일에 번들 하기 위한 패키징 아카이브(AFS)도 있습니다.
이 포맷의 버전2(ADX2)에서는 HCA 및 HCA-MX 확장자를 사용합니다.이 확장자는 보통 확장자가 ACB 및 AWB인 컨테이너 파일에 번들되어 있습니다.AWB 확장자는 같은 확장자의 Audio 형식과 혼동하지 않고 대부분 HCA 파일의 바이너리 데이터가 포함되어 있습니다.
개요
CRI ADX는 압축 오디오 형식이지만 MP3나 이와 유사한 형식과는 달리 심음향 모델을 적용하지 않아 사운드의 복잡성을 줄일 수 있습니다.대신 ADPCM 모델은 예측 함수와 관련된 오류를 기록하여 샘플을 저장합니다. 즉, ADPCM 압축은 상대적으로 작은 샘플 크기(일반적으로 4비트)를 사용하여 표시의 정확성을 크기와 맞바꾸러한 ADPCM 압축은 부호화 프로세스에서 더 많은 원래 신호가 살아남음을 의미합니다.이로 인해 발생하는 소음에 대한 인간 청각 시스템의 내성은 정확성의 손실을 거의 눈에 띄지 않게 한다.
다른 인코딩 형식과 마찬가지로 CRI ADX는 22050Hz, 44100Hz, 48000Hz 등의 여러 샘플링 주파수를 지원하지만 일반적으로 이미 언급한 정밀도가 부족하기 때문에 출력 샘플 깊이가 16비트로 잠겨 있습니다.여러 채널을 지원하지만 파일 형식 자체는 최대 255개의 채널을 나타낼 수 있지만 스테레오(2채널) 오디오에는 암묵적인 제한이 있는 것 같습니다.CRI ADX를 IMA ADPCM과 같은 대안과 구별하는 유일한 특별한 기능은 통합 루프 기능이며, 이를 통해 오디오 플레이어는 트랙에서 지정된 단일 지점에 도달한 후 선택적으로 뒤로 건너뛰어 일관된 루프를 생성할 수 있습니다.가정적으로는 다음과 같습니다.의 기능은 앞으로 건너뛰기에도 사용할 수 있지만 오디오를 편집 프로그램으로 클리핑할 수 있기 때문에 중복됩니다.
재생에는 WinAmp용 플러그인과 Wave로 변환 도구가 몇 가지 있습니다(참조 항목 참조).오픈 소스 프로그램/라이브러리 FFmpeg에는 CRI ADX 지원도 구현되어 있지만, 디코더는 하드 코딩되어 있기 때문에 44100Hz ADX만 올바르게 디코딩할 수 있습니다.
기술 설명
CRI ADX 사양은 자유롭게 이용할 수 없지만 구조의 가장 중요한 요소는 리버스 엔지니어링되어 웹상의 다양한 장소에서 문서화되어 있습니다.여기서 설명하는 정보는 불완전할 수 있지만 동작하는 코덱 또는 트랜스코더를 구축하기에 충분합니다.
덧붙여서, CRI ADX가 때때로 팩되는 AFS 아카이브 파일은 이름이 아닌 수치 인덱스를 사용하여 내용을 식별하는 단순한 타볼 변형입니다.추출기의 소스 코드는 ADX 아카이브에 있습니다.[2]
파일 헤더
ADX 디스크 형식은 빅 엔디안으로 정의됩니다.메인 헤더의 식별된 섹션을 다음에 나타냅니다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0 | 0x80 | 0x00 | 저작권 오프셋 | 부호화 타입 | 블록 크기 | 샘플 비트 깊이 | 채널 수 | 샘플 레이트 | 샘플의 합계 | |||||||
0x10 | 하이패스 주파수 | 버전 | 플래그 | 루프 얼라인먼트샘플(v3) | 루프가 유효(v3) | 루프가 유효(v3) | 루프 시작 샘플인덱스(v3) | |||||||||
0x20 | 루프 시작 바이트 인덱스(v3) | 루프 활성화(v4) 루프 엔드 샘플인덱스(v3) | 루프 시작 샘플인덱스(v4) 루프 엔드 바이트 인덱스(v3) | 루프 시작 바이트 인덱스(v4) | ||||||||||||
0x30 | 루프 엔드 샘플인덱스(v4) | 루프 종료 바이트 인덱스(v4) | 0바이트 이상의 빈 공간 | |||||||||||||
??? | [ CopyrightOffset - 2 ] ASCII (미종단) 문자열: "(C)CRI" | |||||||||||||||
... | [Copyright Offset + 4] 오디오 데이터는 여기서 시작합니다 |
"Unknown"이라고 표시된 필드는 알 수 없는 데이터를 포함하거나 단순히 예약된 필드(예: 늘 바이트로 채워짐)입니다.'v3' 또는 'v4'로 레이블이 지정된 필드는 둘 다 표시되지 않은 버전에서 "알 수 없음"으로 간주됩니다.이 헤더는 저작권 오프셋에 의해 결정되는 20바이트(0x14)만큼 짧을 수 있습니다.이것에 의해, 이러한 필드가 존재하지 않기 때문에, 루프에 대한 서포트가 암묵적으로 배제됩니다.
"Encoding Type" 필드에는 다음 중 하나가 포함됩니다.
- 예측 계수가 사전 설정된 CRI ADX의 경우 0x02
- 0x03(표준 CRI ADX용)
- 지수 척도의 CRI ADX의 경우 0x04
- AHX의 경우 0x10 또는 0x11
"Version" 필드에는 다음 중 하나가 포함됩니다.
- CRI ADX '버전 3'의 경우 0x03
- CRI ADX '버전 4'의 경우 0x04
- 루프 지원이 없는 CRI ADX 4의 변형인 경우 0x05
AHX 오디오를 디코딩할 때 버전필드는 아무런 의미가 없는 것처럼 보이며 무시해도 무방합니다.
인코딩 유형이 '2'인 파일은 다음과 같이 4개의 가능한 예측 계수 집합을 사용합니다.
계수 0 | 계수 1 | |
---|---|---|
0 을 설정 | 0x0000 | 0x0000 |
세트 1 | 0x0F00 | 0x0000 |
세트 2 | 0x1CC0 | 0xF300 |
세트 3 | 0x1880 | 0xF240 |
샘플 형식
CRI ADX 부호화 오디오 데이터는 일련의 '블록'으로 분할되며, 각 블록에는 한 채널만의 데이터가 포함됩니다.그런 다음 블록은 모든 채널에서 오름차순으로 1개의 블록으로 구성된 '프레임'으로 배치됩니다.예를 들어 스테레오(2채널) 스트림에서는 프레임1: 왼쪽 채널블록, 오른쪽 채널블록, 프레임2: 왼쪽, 오른쪽 등으로 구성됩니다.블록의 크기는 보통 4비트샘플을 포함한 18바이트이지만 다른 사이즈는 기술적으로 가능합니다.이러한 블록의 예는 다음과 같습니다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
예측 변수/척도 | 4비트 샘플x 32 |
'예측 변수/척도' 정수의 처음 3비트는 예측 변수를 포함합니다.스케일은 나머지 13비트에 포함됩니다.
예측지수는 해당 블록을 디코딩하는 데 사용해야 하는 예측계수 세트를 지정하는 3비트 정수입니다.이것은 인코딩 유형이 '2'인 파일에서만 사용됩니다.
스케일은 13비트 부호 없는 정수(헤더와 같은 빅 엔디안)로, 기본적으로 해당 블록의 모든 샘플을 증폭하는 것입니다.블록 내의 각 샘플은 비트스트림 순서로 디코딩해야 합니다.즉, 최상위 비트가 먼저 디코딩해야 합니다.예를 들어 샘플 사이즈가 4비트인 경우:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
첫 번째 샘플 | 두 번째 샘플 |
샘플 자체는 역방향으로 되어 있지 않기 때문에 일단 추출하면 만지작거릴 필요가 없습니다.각 샘플은 서명되어 이 예에서는 값이 -8 ~ +7(디코딩 중 스케일에 곱함) 사이일 수 있습니다.한편, 헤더에 의해 1~255의 비트 깊이가 가능합니다.1비트 샘플은 노래 인코딩에 특별히 유용하지 않은 값 {0, 1, {-1, 0} 또는 {-1, 1)만을 나타낼 수 있기 때문에 발생할 가능성이 거의 없습니다.이러한 샘플이 발생하더라도 3가지 중 어느 것이 올바른 해석인지 불명확합니다.
CRI ADX 디코딩
이 섹션에서는 "Encoding Type"이 "Standard CRI ADX"(0x03)인 경우 CRI ADX 'version 3' 또는 'version 4' 디코딩에 대해 설명합니다.인코더는 단순히 코드를 뒤집어서 역방향으로 실행함으로써 구축될 수도 있습니다.이 섹션의 모든 코드샘플은 C99를 사용하여 작성됩니다.
'표준' CRI ADX를 인코딩 또는 디코딩하기 전에 예측 계수 집합을 계산해야 합니다.이는 일반적으로 초기화 단계에서 가장 잘 수행됩니다.
#정의 M_PI acos(-1.0) 이중으로 하다 a, b, c; a = sqrt(2.0) - 왜냐하면(2.0 * M_PI * ((이중으로 하다)adx_filename(adx_filename)->하이패스_주파수 / adx_filename(adx_filename)->sample_rate)); b = sqrt(2.0) - 1.0; c = (a - sqrt((a + b) * (a - b))) / b; //(a+b)*(a-b) = a*a-b*b이지만 더 간단한 공식은 부동 소수점에서의 정확도를 잃습니다. // 이중 계수 [2]; 계수[0] = c * 2.0; 계수[1] = -(c * c);
이 코드는 이전 두 표본에서 현재 표본을 예측하기 위한 예측 계수를 계산합니다.이러한 계수는 1차 유한 임펄스 응답 하이패스 필터도 형성합니다.[clarification needed]
디코딩 계수를 알게 되면 스트림 디코딩을 시작할 수 있습니다.
static int32_t* past_count; // 각 채널에서 이전에 디코딩된 샘플로 시작 시 제로 처리됨(size = 2*channel_count) static uint_fast32_t sample_index = 0; // sample_index는 다음 스태틱 ADX_header* adx_needed 샘플이 디코딩되어야 하는 샘플 세트 인덱스입니다. /////// 버퍼는 디코딩된 샘플이 필요한 위치입니다.버퍼를 채우려면 많은 샘플 'sets'(모든 채널에서 하나의 샘플)를 디코딩해야 합니다// looping_enabled는 내장 루프의 사용을 제어하는 부울 플래그입니다// 버퍼에서 서명되지 않은 디코드_adx_standard(EOS)의 샘플 'sets' 수를 반환합니다(int16_t* 버퍼, 서명되지 않은 samples_needed, boople_enabled.표시된 const samples_per_block)두;만약(;&.!adx_header->, loop_enabled 및 looping_enabled) 돌아선 거짓, 끓여Loop looping_enabled 때까지 샘플의 요청 수, 혹은(samples_n 파일의 끝에 도달한 경우를 디코딩은 아침 8/adx_header->, sample_bitdepth,int16_t scale[adx_header->, channel_count](adx_header->, block_size-2).Eeded>0&&sample_.지수<>adx_header->, total_samples){을 끓여;부호 없는 samples_can_get=samples_per_block-sample_offset, 현재 블록 부호 없는 sample_offset에)sample_index%samples_per_block를 완전 해독되기 쉬워요 견본의 수를 산정하다//널판자 샘플을 받는 동안 이 달리기 만약 그들이 안 맞의 버퍼 만약(samples_can_.사용할 수 있다. Samples_needed)samples_can_get=samples_needed.//널판자 샘플 수를 현재 스트림이 충분히 또는(;&, sample_index+samples_can_get>adx_header->, loop_end_index 및 looping_enabled)samples_can_get=adx_header-> 루프 트리거가 근처에 있지 않다 얻게 될;loop_end_index-sample_index, 다른 경우(sample_index+.samples_can_get >adx_header->, total_samples)samples_can_get=adx_header->, total_samples-sample_index, //고 해당 위치를 기록하는 sample_index가 상주하는 프레임의 시작의 비트 주소. unsigned 긴 started_at=(adx_header-> Calculate, copyright_offset+4+)sample_index/samples_per_block*adx_header->, block_size*adx_he.ader->, channel_cOunt)*8명이며 끓여각 블록의(i=0;나는 <, adx_header->, channel_count, ++i는 부호 없는){bitstream_seek(started_at+adx_header->, block_size!나는 그대 8), scale[나는])ntohs(bitstream_read(16).}을 끓여 이 프레임은 시작부터 Pre-calculate 규모를 값 sample_offset는 부호 없는 sample_endoffset)samp의 정류장 값을 많이 읽는다.le_offset+samples_can_get, // 규모 직후 프레임의 첫번째 블록에서 started_at += 16;(i=0;나는 <, adx_header->, channel_count, ++i는 부호 없는)에(sample_offset<>sample_endoffset){{을 끓여다음 샘플 더블 sample_prediction)coefficient[0]*past_s을 예측한 첫번째 샘플의 bitstream 주소 저장합니다.amples는 경우에는 i*2+ 0-RSB-+coefficient[1]*past_samples[i*2+1], // 샘플은 오프셋에, 읽고32bit 정수를 끓여사인 익스텐션을 구현하는 것은 독자들을 위해 그 사인 익스텐션 // 운동으로써 남게 된다 그것을 확장할 수에 서명하다 몰려드는은 이상 8비트bitstream_seek(started_at+adx_header->, sample_bitd은 메모리 조정을 포함해야 할 것이다.유능한H*sample_offset+)adx_header->, block_size 두 8*명확히 설명);int_fast32_t sample_error)bitstream_read(adx_header->, sample_bitdepth), sample_error)sign_extend(sample_error, adx_header->, sample_bitdepth), // 규모 오류 보정 값 sample_error *= scale[나는], // Calculate의 표본에 의해를 결합하는 예측과 함께 erro.r정확한이온 int_fast32_t 샘플=sample_error+(int_fast32_t)sample_prediction, // 업데이트를 지난 견본들과 더 새로운 샘플 past_samples[i*2+1]=past_samples[i*2+0], past_samples[i*2+0])표본//널판자를 표본과 유효한 범위에 대한 16비트 정수 만약(샘플>32767)샘플=32767, 다른 경우(샘플<>-32768). 샘플 = -32768; // 샘플을 버퍼에 저장한 다음 *sample+= sample; } ++sample_sample; // 모든 블록에서 샘플을 하나씩 디코딩했습니다. 블록 오프셋을 1 ++sample_index; // 이것은 또한 스트림에 샘플이 하나 더 추가되었음을 의미합니다. --sample_needed; //// 따라서 디코딩해야 할 샘플 세트가 하나 적습니다. // 루프 종료 마커를 눌렀는지 확인합니다.루프 시작까지 점프할 필요가 있는 경우 (looping_enabled & sample_index == adx_displate-> loop_start_index;} sample_index = adx_displays-> loop_start_index; } returnores_needed; }
위의 코드 대부분은 C에 정통한 사람이라면 충분히 알기 쉬울 것입니다.'ADX_header
포인터는 앞서 설명한 것처럼 헤더에서 추출된 데이터를 나타냅니다.이미 호스트 Endian으로 변환된 것으로 간주됩니다.이 실장은 최적인 것이 아니고, 부호 확장의 특정 방법이나 파일 또는 네트워크 소스에서 비트스트림을 취득하는 방법 등, 외부의 염려가 무시되고 있습니다.완료되면 출력 버퍼에 샘플의 sample_needed 세트가 있습니다(예를 들어 스테레오의 경우 쌍이 있습니다).디코딩된 샘플은 호스트 엔디언 표준 인터리브 PCM 형식(예: 왼쪽 16비트, 오른쪽 16비트, 왼쪽, 오른쪽 등)입니다.마지막으로 루프가 네이블이 아니거나 지원되지 않는 경우 버퍼에서 사용되지 않은 샘플공간 수가 반환됩니다.발신자는 이 값이 제로가 아닌지를 테스트하여 스트림의 끝을 검출하고 필요에 따라 사용되지 않는 공간에 무음을 드롭 또는 쓸 수 있습니다.
암호화
CRI ADX는 XOR가 블록 스케일 값과 함께 선형 합동 의사 난수 생성기에서 값을 매기는 단순한 암호화 방식을 지원합니다.이 방법은 (CRI ADX의 실시간 디코딩에 따라) 복호화 비용이 저렴하지만 암호화된 파일을 사용할 수 없게 만듭니다.헤더의 "Flags" 값이 0x08일 때 암호화가 활성화됩니다.XOR은 대칭이기 때문에 암호화와 같은 방법으로 복호화됩니다.암호화 키는 선형 합동 생성기의 승수, 증분 및 시작 값(유효 블록스케일의 15비트 범위 값을 유지하기 위한 계수는 0x8000)의 3가지 16비트 값 세트입니다.통상, 1개의 게임의 모든 ADX 파일은 같은 키를 사용합니다.
암호화 방식은 기존 플레인텍스트 공격에 취약합니다.같은 오디오의 암호화되지 않은 버전이 알려진 경우 난수 스트림을 쉽게 검색할 수 있으며, 이 스트림을 통해 키 파라미터를 결정할 수 있으므로 동일한 키로 암호화된 모든 CRI ADX를 복호화할 수 있습니다.암호화 방식에서는 사일런트블록(모든 샘플의 nybl이 0)으로 알려져 있기 때문에 암호화하지 않음으로써 이 문제를 더욱 어렵게 하려고 합니다.
암호화된 CRI ADX가 유일한 샘플이라고 해도 복호화된 CRI ADX의 스케일 값이 "저범위" 내에 있어야 한다고 가정함으로써 키를 결정할 수 있다.단, 이 방법은 파일 암호화에 사용되는 키를 반드시 찾을 필요는 없습니다.항상 올바른 출력을 생성하는 키를 판별할 수 있지만 오류가 검출되지 않을 수 있습니다.이는 스케일 값의 하위 비트가 점점 랜덤하게 분산되기 때문에 암호화에 의해 추가된 랜덤성과 분리할 수 없게 됩니다.
AHX 복호화
앞서 설명한 바와 같이 AHX는 MPEG2 오디오의 구현일 뿐이며 디코딩 방법은 기본적으로 표준과 동일하며 CRI ADX 컨테이너에서 스트림을 분리하여 mpg123과 같은 표준 MPEG 오디오 디코더를 통해 전송할 수 있습니다.CRI ADX 헤더의 「샘플레이트」와 「총샘플수」는, 디코더가 필요로 하는 경우(인코더/멀서 실장에 의해서 설정할 필요가 있습니다), 통상은 「블록 사이즈」나 「샘플 비트 깊이」등의 그 외의 필드의 대부분은 제로입니다.위에서 설명한 바와 같이, 루프 기능도 사용할 수 없습니다.
레퍼런스
- ^ https://imgur.com/rPTv8K2
- ^ "Title Unknown". Archived from the original on 2009-03-18.