2009-04-11 33 views
5

Tôi đang bị biến dạng nhẹ (nghe có vẻ như ù) trong nền khi tôi chạy mã sau đây. Bởi vì bản chất tinh tế của nó, nó làm cho tin rằng có một số loại răng cưa xảy ra với việc đúc byte.Tiếng ồn ở chế độ nền khi tạo sóng sin trong Java

AudioFormat = PCM_SIGNED 44100,0 Hz, 16 bit, âm thanh stereo, 4 byte/khung, lớn-endian

Note: Mã giả (bây giờ) mà dữ liệu được trong cuối lớn.

public static void playFreq(AudioFormat audioFormat, double frequency, SourceDataLine sourceDataLine) 
{ 
    System.out.println(audioFormat); 
    double sampleRate = audioFormat.getSampleRate(); 
    int sampleSizeInBytes = audioFormat.getSampleSizeInBits()/8; 
    int channels = audioFormat.getChannels(); 

    byte audioBuffer[] = new byte[(int)Math.pow(2.0, 19.0) * channels * sampleSizeInBytes]; 

    for (int i = 0; i < audioBuffer.length; i+=sampleSizeInBytes*channels) 
    { 
     int wave = (int) (127.0 * Math.sin(2.0 * Math.PI * frequency * i/(sampleRate * sampleSizeInBytes * channels)) ); 

     //wave = (wave > 0 ? 127 : -127); 

     if (channels == 1) 
     { 
      if (sampleSizeInBytes == 1) 
      { 
       audioBuffer[i] = (byte) (wave); 
      } 

      else if (sampleSizeInBytes == 2) 
      { 
       audioBuffer[i] = (byte) (wave); 
       audioBuffer[i+1] = (byte)(wave >>> 8); 
      } 
     } 

     else if (channels == 2) 
     { 
      if (sampleSizeInBytes == 1) 
      { 
       audioBuffer[i] = (byte) (wave); 
       audioBuffer[i+1] = (byte) (wave); 
      } 

      else if (sampleSizeInBytes == 2) 
      { 
       audioBuffer[i] = (byte) (wave); 
       audioBuffer[i+1] = (byte)(wave >>> 8); 

       audioBuffer[i+2] = (byte) (wave); 
       audioBuffer[i+3] = (byte)(wave >>> 8); 
      } 
     } 
    } 

    sourceDataLine.write(audioBuffer, 0, audioBuffer.length); 
} 

Trả lời

7

Nhận xét của bạn nói rằng mã giả định người dùng lớn.

Về mặt kỹ thuật bạn thực xuất ra trong ít về cuối nhỏ, tuy nhiên nó dường như không quan trọng vì thông qua một những đứa may mắn byte quan trọng nhất của bạn luôn luôn là 0.

EDIT: để giải thích rằng tiếp tục - khi giá trị của bạn có giá trị tối đa là 127, bạn phải viết (0x00, 0x7f), nhưng đầu ra thực tế từ mã của bạn là (0x7f, 0x00) là 32512. Điều này xảy ra gần giá trị tối đa 16 bit thích hợp của 32767, nhưng với 8 bit dưới cùng thì không. Nó sẽ là tốt hơn để luôn luôn sử dụng 32767 là giá trị tối đa, và sau đó loại bỏ 8 bit dưới nếu cần thiết.

Điều này có nghĩa rằng mặc dù bạn đang xuất dữ liệu 16 bit, độ phân giải hiệu dụng chỉ là 8 bit. Điều này dường như là do thiếu chất lượng âm thanh.

Tôi đã tạo một phiên bản mã của bạn chỉ đưa dữ liệu thô vào một tệp và không thể thấy bất kỳ điều gì khác sai với bit tự dịch chuyển. Không có thay đổi bất ngờ của dấu hiệu hoặc bit bị thiếu, nhưng có một buzz phù hợp với chất lượng mẫu 8 bit.

Ngoài ra, cho những gì nó có giá trị toán học của bạn sẽ dễ dàng hơn nếu bạn tính toán phương trình sóng dựa trên số lượng mẫu, và sau đó lo lắng về hiệu số byte riêng:

int samples = 2 << 19; 
byte audioBuffer[] = new byte[samples * channels * sampleSizeInBytes]; 

for (int i = 0, j = 0; i < samples; ++i) 
{ 
    int wave = (int)(32767.0 * Math.sin(2.0 * Math.PI * frequency * i/sampleRate)); 
    byte msb = (byte)(wave >>> 8); 
    byte lsb = (byte) wave; 

    for (int c = 0; c < channels; ++c) { 
     audioBuffer[j++] = msb; 
     if (sampleSizeInBytes > 1) { 
      audioBuffer[j++] = lsb; 
     } 
    } 
} 
+0

Ah! Xem lỗi ngay bây giờ, sau khi sửa phần biên độ, lỗi trở nên rất rõ ràng, nhưng mã của bạn cũng hiệu quả hơn. Cảm ơn! – yxk

+0

Phân tích tốt! –

2

Tôi cho rằng bạn đang gọi mã này nhiều lần để phát âm thanh dài.

Có khả năng sóng mà bạn đang tạo không hoàn thành một khoảng thời gian đầy đủ trước khi nó được viết không?

Nếu sóng bị "cắt" trước khi nó hoàn thành một khoảng thời gian đầy đủ và sau đó sóng tiếp theo được ghi vào đầu ra, bạn chắc chắn sẽ nghe thấy điều gì đó lạ và tôi cho rằng đó có thể là nguyên nhân gây ra tiếng ù.

Ví dụ:

 /-------\    /-------\    /-------\ 
    -----/   \  -----/   \  -----/   \ 
        \      \      \ 
        \-----     \-----     \----- 

Thông báo sự ngắt kết nối giữa các phần của làn sóng này. Điều đó có thể gây ra tiếng ù.

+0

Vâng, nó không phải là vấn đề mà vì bộ đệm là đủ lớn để âm thanh trải qua nhiều chu kỳ. Nó không tính đến các nhấp chuột nhưng không cho âm thanh ù liên tục. – yxk

+0

đây không phải là câu trả lời đúng - mã rõ ràng tạo ra nhiều mẫu và không cắt ngắn ở cuối mỗi chu kỳ – Alnitak

+0

và tôi đã kiểm tra mã để kiểm tra - đó là lỗi lượng tử bit 8 vô ý gây ra tiếng vang. – Alnitak

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