áp phích đầu tiên tại đây. Tôi thường thích tìm câu trả lời cho bản thân mình (có thể là thông qua nghiên cứu hoặc thử nghiệm và lỗi), nhưng tôi bị bối rối ở đây.Âm thanh Android - Truyền trực tuyến hành vi kỳ lạ của máy phát điện sin
Tôi đang cố gắng làm: Tôi đang tạo một bộ tổng hợp âm thanh Android đơn giản. Ngay bây giờ, tôi chỉ đang chơi một sine-tone trong thời gian thực, với một thanh trượt trong giao diện người dùng thay đổi tần số của giai điệu khi người dùng điều chỉnh nó.
Cách tôi đã tạo nó: Về cơ bản, tôi có hai luồng - một chuỗi công nhân và một chuỗi đầu ra. Chuỗi công nhân chỉ đơn giản là điền vào một bộ đệm với dữ liệu sóng sin mỗi khi phương thức tick() của nó được gọi. Khi bộ đệm được lấp đầy, nó sẽ cảnh báo luồng đầu ra rằng dữ liệu đã sẵn sàng để ghi vào rãnh ghi âm. Lý do tôi đang sử dụng hai chủ đề là vì các khối audiotrack.write() và tôi muốn chuỗi công nhân có thể bắt đầu xử lý dữ liệu của mình càng sớm càng tốt (thay vì chờ bản âm thanh kết thúc bằng văn bản). Thanh trượt trên giao diện người dùng chỉ đơn giản là thay đổi một biến trong chuỗi công nhân, để bất kỳ thay đổi nào về tần số (thông qua thanh trượt) sẽ được đọc bằng phương thức tick() của chuỗi công nhân.
Điều gì hoạt động: Hầu hết mọi thứ; Các chủ đề giao tiếp tốt, dường như không có bất kỳ khoảng trống hoặc nhấp chuột nào trong khi phát lại. Mặc dù kích thước bộ đệm lớn (nhờ android), sự đáp ứng là OK. Biến tần số không thay đổi, cũng như các giá trị trung gian được sử dụng trong các phép tính đệm trong phương thức tick() (được xác minh bởi Log.i()).
Điều gì không hoạt động: Vì lý do nào đó, dường như tôi không thể thay đổi tần suất âm thanh liên tục. Khi tôi điều chỉnh thanh trượt, tần suất thay đổi theo các bước, thường rộng bằng phần tư hoặc phần năm. Về mặt lý thuyết, tôi nên nghe những thay đổi như phút 1Hz, nhưng tôi thì không. Kỳ lạ thay, có vẻ như những thay đổi đối với thanh trượt làm cho sóng sin phát qua các khoảng thời gian trong chuỗi điều hòa; Tuy nhiên, tôi có thể xác minh rằng biến tần số là không chụp đến bội số nguyên của tần số mặc định.
track âm thanh của tôi được thiết lập như vậy: đệm
_buffSize = AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
_audioTrackOut = new AudioTrack(AudioManager.STREAM_MUSIC, _sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, _buffSize, AudioTrack.MODE_STREAM);
Các chủ đề công nhân đang được dân cư (thông qua đánh dấu()) như vậy:
public short[] tick()
{
short[] outBuff = new short[_outBuffSize/2]; // (buffer size in Bytes)/2
for (int i = 0; i < _outBuffSize/2; i++)
{
outBuff[i] = (short) (Short.MAX_VALUE * ((float) Math.sin(_currentAngle)));
//Update angleIncrement, as the frequency may have changed by now
_angleIncrement = (float) (2.0f * Math.PI) * _freq/_sampleRate;
_currentAngle = _currentAngle + _angleIncrement;
}
return outBuff;
}
Các dữ liệu âm thanh đang được viết như này:
_audioTrackOut.write(fromWorker, 0, fromWorker.length);
Mọi trợ giúp sẽ được đánh giá cao. Làm thế nào tôi có thể nhận được nhiều thay đổi dần dần về tần suất? Tôi khá tự tin rằng logic của tôi trong tick() là âm thanh, như Log.i() xác minh rằng các biến angleIncrement và currentAngle đang được cập nhật đúng cách.
Cảm ơn bạn!
Cập nhật:
Tôi tìm thấy một vấn đề tương tự ở đây: Android AudioTrack buffering problems Các giải pháp đề xuất rằng người ta phải có khả năng để sản xuất mẫu đủ nhanh cho AudioTrack, có ý nghĩa. Tôi hạ thấp tốc độ mẫu xuống 22050Hz và chạy một số thử nghiệm thực nghiệm - tôi có thể lấp đầy bộ đệm của mình (thông qua đánh dấu()) trong khoảng 6ms trong trường hợp xấu nhất. Điều này là quá đủ. Tại 22050Hz, audioTrack cho tôi kích thước bộ đệm 2048 mẫu (hoặc 4096 byte). Vì vậy, mỗi bộ đệm đầy sẽ kéo dài ~ 0.0928 giây âm thanh, dài hơn nhiều so với thời gian để tạo dữ liệu (1 ~ 6 ms). SO, tôi biết rằng tôi không có bất kỳ vấn đề sản xuất mẫu đủ nhanh.
Tôi cũng nên lưu ý rằng trong khoảng 3 giây đầu tiên của vòng đời ứng dụng, nó hoạt động tốt - một thao tác quét trơn tru của thanh trượt tạo ra một thao tác quét trơn tru trong đầu ra âm thanh. Sau này, nó bắt đầu để có được thực sự choppy (âm thanh chỉ thay đổi về mỗi 100Mhz), và sau đó, nó dừng đáp ứng đầu vào thanh trượt ở tất cả.
Tôi cũng đã sửa một lỗi nhưng tôi không nghĩ rằng nó có hiệu lực. AudioTrack.getMinBufferSize() trả về kích thước bộ đệm nhỏ nhất cho phép trong BYTES, và tôi đã sử dụng số này làm chiều dài của bộ đệm trong dấu tick() - Bây giờ tôi sử dụng một nửa số này (2 Byte cho mỗi mẫu).
Bạn sử dụng sự kiện nào để '_freq' thay đổi? Có thực sự thay đổi 1Hz mỗi lần không? Xin lỗi, tôi không hiểu rõ phần ** Những gì không hoạt động ** của bạn. Bạn có thể cung cấp một mẫu mã làm việc đầy đủ hoặc một đoạn âm thanh tổng hợp để làm cho nó có thể ** nghe ** vấn đề của bạn. Đối với đoạn âm thanh: định dạng dữ liệu âm thanh thô là ok - chỉ cần ghi bộ đệm của bạn vào tệp chứ không phải vào thẻ âm thanh. Ví dụ: 16 bit/ký/mono/44100 Hz. –
Để thay đổi _freq, tôi đang sử dụng một OnSeekBarChangeListener ghi một giá trị int mới vào _freq thông qua onProgressChanged(). Tuy nhiên, tôi cũng đã thử sử dụng các nút (lên/xuống) để tăng tần số lên 1 Hz, và chỉ có một sự khác biệt rõ ràng về âm thanh sau nhiều, nhiều gia số (như âm thanh nhảy vào khoảng một phần 3 hoặc 4 , thay vì 1Hz). Đây là một ví dụ về những gì đang xảy ra; Đây là những gì tôi nghe thấy khi tôi từ từ trượt thanh trượt lên và xuống, tăng tần số với mức tăng 1Hz. (từ ~ 200 - ~ 1000Hz): http://www.sendspace.com/file/tpxuwr – Tsherr
Tôi đã tìm thấy một vấn đề tương tự trực tuyến, nhưng giải pháp đề xuất của nó không có tác dụng - xem phần cập nhật ở trên. – Tsherr