2012-04-09 15 views
5

Tôi mới sử dụng nền tảng iOS và C, nhưng không phải là lập trình nói chung. Tình trạng khó xử của tôi là thế này. Tôi đang thực hiện một hiệu ứng echo trong một ứng dụng dựa trên AudioUnits phức tạp. Ứng dụng cần reverb, echo và compression, trong số những thứ khác. Tuy nhiên, tiếng vang chỉ hoạt động ngay khi tôi sử dụng định dạng AudioStreamBasicDescription cụ thể cho các mẫu âm thanh được tạo trong ứng dụng của tôi. Tuy nhiên, định dạng này không hoạt động với các AudioUnits khác. Trong khi có nhiều cách khác để giải quyết vấn đề này, sửa lỗi bit-twiddling trong thuật toán echo có thể là cách tiếp cận thẳng tiến nhất.Các mẫu âm thanh chuyển dịch bit từ Float32 đến SInt16 dẫn đến việc cắt giảm nghiêm trọng

Các * AudioStreamBasicDescription * làm việc với tiếng vang có mFormatFlag của: kAudioFormatFlagsAudioUnitCanonical; Nó chi tiết cụ thể như sau:

AudioUnit Stream Format (ECHO works, NO AUDIO UNITS) 
Sample Rate:    44100 
Format ID:     lpcm 
Format Flags:    3116 = kAudioFormatFlagsAudioUnitCanonical 
Bytes per Packet:    4 
Frames per Packet:   1 
Bytes per Frame:    4 
Channels per Frame:   2 
Bits per Channel:   32 
Set ASBD on input 
Set ASBD on output 
au SampleRate rate: 0.000000, 2 channels, 12 formatflags, 1819304813 mFormatID, 16 bits per channel 

Định dạng dòng làm việc với AudioUnits là như nhau ngoại trừ mFormatFlag: kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved - chi tiết cụ thể của nó là:

AudioUnit Stream Format (NO ECHO, AUDIO UNITS WORK) 
Sample Rate:    44100 
Format ID:     lpcm 
Format Flags:    41 
Bytes per Packet:    4 
Frames per Packet:   1 
Bytes per Frame:    4 
Channels per Frame:   2 
Bits per Channel:   32 
Set ASBD on input 
Set ASBD on output 
au SampleRate rate: 44100.000000, 2 channels, 41 formatflags, 1819304813 mFormatID, 32 bits per channel 

Để tạo hiệu ứng tiếng vang tôi sử dụng hai chức năng mà cắn ca dữ liệu mẫu vào SInt16 không gian, và ngược lại. Như tôi đã nói, điều này phù hợp với định dạng kAudioFormatFlagsAudioUnitCanonical, chứ không phải định dạng khác. Khi nó không thành công, âm thanh bị cắt bớt và méo mó, nhưng chúng ở đó. Tôi nghĩ điều này cho thấy sự khác biệt giữa hai định dạng này là cách dữ liệu được sắp xếp trong Float32.

// convert sample vector from fixed point 8.24 to SInt16 
void fixedPointToSInt16(SInt32 * source, SInt16 * target, int length) { 
    int i; 
    for(i = 0;i < length; i++) { 
     target[i] = (SInt16) (source[i] >> 9); 
     //target[i] *= 0.003; 

    } 
} 

* Như bạn thấy, tôi đã sửa đổi biên độ của các mẫu để loại bỏ việc cắt - rõ ràng không hiệu quả.

// convert sample vector from SInt16 to fixed point 8.24 
void SInt16ToFixedPoint(SInt16 * source, SInt32 * target, int length) { 
    int i; 
    for(i = 0;i < length; i++) { 
     target[i] = (SInt32) (source[i] << 9); 
     if(source[i] < 0) { 
      target[i] |= 0xFF000000; 
     } 
     else { 
      target[i] &= 0x00FFFFFF; 
     } 
    } 
} 

Nếu tôi có thể xác định sự khác biệt giữa kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved, sau đó tôi có thể sửa đổi các phương thức trên cho phù hợp. Nhưng tôi không chắc chắn làm thế nào để con số đó ra. Tài liệu trong CoreAudio là bí ẩn, nhưng từ những gì tôi đã đọc ở đó và lượm lặt từ tệp CoreAudioTypes.h, cả hai mFormatFlag (s) tham chiếu đến định dạng Điểm cố định 8.24 tương tự. Rõ ràng một cái gì đó là khác nhau, nhưng tôi không thể tìm ra những gì.

Cảm ơn bạn đã đọc qua câu hỏi dài này và cảm ơn trước vì bất kỳ thông tin chi tiết nào bạn có thể cung cấp.

+0

Tôi bằng cách nào đó nghi ngờ rằng bạn đang gặp biến dạng hơn là cắt bớt, rất có thể là do lật dấu. Bạn có thể gửi một tập tin WAV được tạo ra bởi thuật toán của bạn ở đây để chúng ta có thể thấy những gì đang xảy ra? –

+0

Ứng dụng của tôi phát âm thanh như một nhạc cụ. Nó không tạo hoặc lưu trữ các tệp sóng. Nhưng tôi nghĩ bạn đúng. Về cơ bản, nếu tôi biết định dạng * kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved * đại diện, tôi có thể tìm ra cách bit-twiddle định dạng trong và ngoài SInt16. Hiện tại, tất cả những gì tôi biết là nó không phải là FixedPoint 8.24 –

Trả lời

11

kAudioFormatFlagIsFloat có nghĩa là bộ đệm chứa các giá trị dấu phẩy động. Nếu mBitsPerChannel là 32 thì bạn đang xử lý float dữ liệu (còn được gọi là Float32) và nếu đó là 64, bạn đang xử lý dữ liệu double.

kAudioFormatFlagsNativeEndian đề cập đến thực tế là dữ liệu trong bộ đệm khớp với độ cuối của bộ xử lý, do đó bạn không phải lo lắng về việc hoán đổi byte.

kAudioFormatFlagIsPacked có nghĩa là mọi bit trong dữ liệu đều quan trọng.Ví dụ: nếu bạn lưu trữ dữ liệu âm thanh 24 bit trong 32 bit, cờ này sẽ không được đặt.

kAudioFormatFlagIsNonInterleaved có nghĩa là mỗi bộ đệm riêng lẻ bao gồm một kênh dữ liệu. Nó được phổ biến cho dữ liệu âm thanh được xen kẽ, với các mẫu xen kẽ giữa các kênh L và R: LRLRLRLR. Đối với các ứng dụng DSP, thường dễ dàng hơn để loại bỏ dữ liệu và làm việc trên một kênh tại một thời điểm.

Tôi nghĩ trong trường hợp của bạn, lỗi là bạn đang xử lý dữ liệu dấu chấm động làm điểm cố định. Dữ liệu float thường được chia tỷ lệ thành khoảng [-1, +1). Để chuyển đổi float thành SInt16, bạn cần phải nhân mỗi mẫu với giá trị 16 bit tối đa (1u << 15, 32768) và sau đó clip vào khoảng [-32768, 32767].

+0

Cảm ơn câu trả lời đầy đủ thông tin. Trong thực tế, nó xác nhận rất nhiều những gì tôi đã đọc. Tuy nhiên, khi tôi đã cố gắng để đưa các bộ đệm AudioSample để Float32 * trong cuộc gọi lại của tôi, tôi nhận được một cảnh báo. inSamplesLeft = (Float32 *) ioData-> mBuffers [0] .mData; Các kiểu con trỏ không tương thích gán cho 'AudioUnitSampleType *' (aka 'long *') từ 'Float32 *' (aka Float32) –

+0

Nếu không thấy mã, thật khó để biết chính xác những gì đang diễn ra, nhưng nói chung bạn không thể truyền từ một 'dài * 'đến một' float * 'và mong đợi để có được kết quả chính xác. – sbooth

+0

Tôi đã đâm khác và nhận được vấn đề này được giải quyết và sau khi đọc lại câu trả lời của bạn tôi đã thực hiện một số tiến bộ tốt. Tôi vẫn còn có rất nhiều biến dạng nhưng tôi nghĩ rằng điều này có thể được gây ra bởi các phương pháp trival mà tôi đang chuyển đổi Float32 để SInt16. Bạn có thể giải thích về cú pháp bit-shift 16 bit mà bạn đã viết - Tôi không phải là lập trình viên C và không chắc chắn cách thực hiện: (1u << 15, 32768) –

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