2010-01-25 42 views
9

Để giảm kích thước tải xuống của ứng dụng iPhone, tôi đang nén một số tệp âm thanh. Cụ thể là tôi đang sử dụng afconvert trên dòng lệnh để thay đổi định dạng .wav thành định dạng .caf w/ima4 compression.Giải mã định dạng âm thanh ima4

Tôi đã đọc this (wooji-juice.com) Bài viết tuyệt vời về chủ đề này chính xác. Tôi gặp sự cố với các gói "giải mã gói ima4". Tôi đã nhìn vào mã mẫu của họ và tôi đang bị mắc kẹt. Xin vui lòng giúp w/một số mã giả hoặc mã mẫu có thể hướng dẫn tôi đi đúng hướng.

Cảm ơn!

thông tin bổ sung: Dưới đây là những gì tôi đã hoàn thành và nơi tôi đang gặp rắc rối ... tôi có thể chơi .wav file trong cả hai mô phỏng và trên điện thoại. Tôi có thể nén các tệp .wav thành .caf w/ima4 nén bằng afconvert trên dòng lệnh. Tôi đang sử dụng SoundEngine mà đến w/CrashLanding (Tôi cố định một rò rỉ bộ nhớ). Tôi đã sửa đổi mã SoundEngine để tìm mFormatID 'ima4'.

Tôi không hiểu bài đăng trên blog được liên kết ở trên bắt đầu bằng w/"Tính toán kích thước của dữ liệu chưa giải nén". Tại sao tôi cần phải làm điều này? Ngoài ra, thuật ngữ "gói" là gì? Tôi rất mới với bất kỳ loại chương trình âm thanh nào.

+0

Cũng nói với mọi người về những gì bạn đang bị mắc kẹt. Bạn đã hoàn tất bước nào và bạn gặp phải vấn đề của mình ở đâu? – Younes

+0

Bạn có phải sử dụng OpenAL không? Bạn chỉ phải tự giải mã nếu bạn đang sử dụng OpenAL, nếu không bạn chỉ có thể xử lý CoreAudio. –

Trả lời

11

Sau khi thu thập tất cả các dữ liệu từ Wooji-Juice, Multimedia WikiApple, đây là đề nghị của tôi (có thể cần một số thí nghiệm):

cấu trúc file

  • của Apple tập tin IMA4 được làm bằng gói 34 byte. Đây là đơn vị gói được sử dụng để xây dựng tệp.
  • Mỗi gói 34 byte có hai phần:
    • 2 byte đầu tiên chứa lời mở đầu: một yếu tố dự báo ban đầu và một số bước
    • 32 byte còn lại chứa các Nibbles âm thanh (một nibble của 4 bit được sử dụng để lấy mẫu 16 bit)
  • Mỗi gói có 32 byte dữ liệu nén, đại diện cho 64 mẫu 16 bit.
  • Nếu tệp âm thanh nổi, các gói được xen kẽ (một cho bên trái, một cho bên phải); phải có một số lượng thậm chí các gói.

Giải mã

Mỗi gói 34 byte sẽ dẫn đến việc giải nén của 64 mẫu của 16 bit. Vì vậy, kích thước của dữ liệu chưa nén là 128 byte cho mỗi gói.

Mã giả giải mã trông giống như:

int[] ima_index_table = ... // Index table from [Multimedia Wiki][2] 
int[] step_table = ... // Step table from [Multimedia Wiki][2] 
byte[] packet = ... // A packet of 34 bytes compressed 
short[] output = ... // The output buffer of 128 bytes 
int preamble = (packet[0] << 8) | packet[1]; 
int predictor = preamble && 0xFF80; // See [Multimedia Wiki][2] 
int step_index = preamble && 0x007F; // See [Multimedia Wiki][2] 
int i; 
int j = 0; 
for(i = 2; i < 34; i++) { 
    byte data = packet[i]; 
    int lower_nibble = data && 0x0F; 
    int upper_nibble = (data && 0xF0) >> 4; 

    // Decode the lower nibble 
    step_index += ima_index_table[lower_nibble]; 
    diff = ((signed)nibble + 0.5f) * step/4; 
    predictor += diff; 
    step = ima_step_table[step index]; 

    // Clamp the predictor value to stay in range 
    if (predictor > 65535) 
     output[j++] = 65535; 
    else if (predictor < -65536) 
     output[j++] = -65536; 
    else 
     output[j++] = (short) predictor; 

    // Decode the uppper nibble 
    step_index += ima_index_table[upper_nibble]; 
    diff = ((signed)nibble + 0.5f) * step/4; 
    predictor += diff; 
    step = ima_step_table[step index]; 

    // Clamp the predictor value to stay in range 
    if (predictor > 65535) 
     output[j++] = 65535; 
    else if (predictor < -65536) 
     output[j++] = -65536; 
    else 
     output[j++] = (short) predictor; 
} 
1

Thuật ngữ "gói" đề cập đến một nhóm các mẫu âm thanh nén có tiêu đề. Bạn cần tiêu đề để giải mã dữ liệu ngay sau đó. Nếu bạn xem tập tin ima4 của bạn là một cuốn sách, thì mỗi gói là một trang. Ở trên cùng là các giá trị cần thiết để giải mã trang đó, tiếp theo là âm thanh nén.

Đó là lý do tại sao bạn cần tính toán kích thước của dữ liệu chưa giải nén (và sau đó tạo không gian cho nó) - vì nó được nén, bạn cần chuyển đổi dữ liệu từ âm thanh nén sang âm thanh không nén trước khi bạn có thể xuất ra. Để cấp phát một bộ đệm đầu ra, bạn cần phải biết nó lớn đến mức nào (lưu ý: bạn có thể cần phải xuất ra các khối lớn hơn một gói đơn tại một thời điểm). Nó trông giống như cấu trúc điển hình, trên phần "Tổng quan" trước đó, là bộ 64 mẫu, mỗi 16 bit (để 128 byte) được dịch sang tiêu đề 2 byte và bộ nén 32 byte mẫu (34 byte trong tất cả). Vì vậy, trong trường hợp điển hình, bạn có thể tạo ra dữ liệu đầu ra dự kiến ​​của mình bằng cách lấy kích thước dữ liệu đầu vào, chia cho 34 để nhận số gói, sau đó nhân với 128 byte cho âm thanh không nén trên mỗi gói.

Bạn không nên làm điều đó. Có vẻ như bạn nên truy vấn kAudioFilePropertyDataFormat để lấy mBytesPerPacket - đây là giá trị "34" ở trên và mFramesPerPacket - đây là 64, ở trên, được nhân với 2 (cho mẫu 16 byte) để tạo 128 byte đầu ra.

Sau đó, đối với mỗi gói, bạn sẽ cần chạy qua phần giải mã được mô tả trong bài đăng. Trong phần còn pseudo C-mã, giả sử bạn đang nhận được mảng byte, để xử lý các tiêu đề:

packet = GetPacket(); 
Header = (packet[0] << 8) | packet[1]; //Big-endian 16-bit value 
step_index = Header & 0x007f; //Lower seven bits 
predictor = Header & 0xff80; //Upper nine bits 
for (i = 2; i < mBytesPerPacket; i++) 
{ 
    nibble = packet[i] & 0x0f; //Low Nibble 
    process that nibble, per the blogpost -- be careful on sign-extension! 
    nibble = (packet[i] & 0xf0) >> 4; //High Nibble 
    process that nibble, per the blogpost -- be careful on sign-extension! 
} 

Dấu hiệu-phần mở rộng trên đề cập đến thực tế là các bài liên quan đến việc xử lý từng nhấm nháp cả trong một unsigned và một đã ký kết. Nếu bit cao của một nibble (bit 3) là 1, thì nó âm; Ngoài ra, sự thay đổi bit có thể làm phần mở rộng dấu. Điều này không được xử lý trong mã giả ở trên.

Các vấn đề liên quan