Tôi muốn lấy bộ đệm byte từ nội dung âm thanh bằng cách sử dụng đối tượng FileDescriptor OpenSL ES, vì vậy tôi có thể enqueue nó lặp đi lặp lại một SimpleBufferQueue, thay vì sử dụng giao diện SL để phát/dừng/tìm kiếm tệp.Có thể lấy bộ đệm byte trực tiếp từ nội dung âm thanh trong OpenSL ES (dành cho Android) không?
Có ba lý do chính khiến tôi muốn quản lý các byte mẫu trực tiếp:
- OpenSL sử dụng một lớp AudioTrack để chơi/dừng/etc cho cầu thủ đối tượng. Điều này không chỉ giới thiệu chi phí không mong muốn, nhưng nó cũng có một số lỗi, và khởi động/dừng nhanh chóng của người chơi gây ra rất nhiều vấn đề.
- Tôi cần phải thao tác bộ đệm byte trực tiếp cho các hiệu ứng DSP tùy chỉnh.
- Các clip tôi sắp phát đều nhỏ và tất cả có thể được tải vào bộ nhớ để tránh phí I/O của tệp. Thêm vào đó, enqueueing bộ đệm của riêng tôi sẽ cho phép tôi giảm độ trễ bằng cách viết 0 cho sink đầu ra, và đơn giản chuyển sang byte mẫu khi chúng đang chơi, thay vì STOPPING, PAUSING và PLAYING AudioTrack.
rồi, do đó biện minh hoàn chỉnh - đây là những gì tôi đã cố gắng - Tôi có một mẫu struct chứa, về cơ bản, một ca khúc đầu vào và đầu ra, và một mảng byte để giữ mẫu. Đầu vào là trình phát FileDescriptor của tôi và đầu ra là một đối tượng SimpleBufferQueue. Dưới đây là cấu trúc của tôi:
typedef struct Sample_ {
// buffer to hold all samples
short *buffer;
int totalSamples;
SLObjectItf fdPlayerObject;
// file descriptor player interfaces
SLPlayItf fdPlayerPlay;
SLSeekItf fdPlayerSeek;
SLMuteSoloItf fdPlayerMuteSolo;
SLVolumeItf fdPlayerVolume;
SLAndroidSimpleBufferQueueItf fdBufferQueue;
SLObjectItf outputPlayerObject;
SLPlayItf outputPlayerPlay;
// output buffer interfaces
SLAndroidSimpleBufferQueueItf outputBufferQueue;
} Sample;
sau khi khởi tạo một cầu thủ tập tin fdPlayerObject và malloc-ing bộ nhớ cho bộ đệm byte của tôi với
sample->buffer = malloc(sizeof(short)*sample->totalSamples);
Tôi nhận được giao diện BufferQueue với
// get the buffer queue interface
result = (*(sample->fdPlayerObject))->GetInterface(sample->fdPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(sample->fdBufferQueue));
Sau đó, tôi khởi tạo trình phát đầu ra đầu ra:
// create audio player for output buffer queue
const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
const SLboolean req1[] = {SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(sample->outputPlayerObject), &outputAudioSrc, &audioSnk,
1, ids1, req1);
// realize the output player
result = (*(sample->outputPlayerObject))->Realize(sample->outputPlayerObject, SL_BOOLEAN_FALSE);
assert(result == SL_RESULT_SUCCESS);
// get the play interface
result = (*(sample->outputPlayerObject))->GetInterface(sample->outputPlayerObject, SL_IID_PLAY, &(sample->outputPlayerPlay));
assert(result == SL_RESULT_SUCCESS);
// get the buffer queue interface for output
result = (*(sample->outputPlayerObject))->GetInterface(sample->outputPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
&(sample->outputBufferQueue));
assert(result == SL_RESULT_SUCCESS);
// set the player's state to playing
result = (*(sample->outputPlayerPlay))->SetPlayState(sample->outputPlayerPlay, SL_PLAYSTATE_PLAYING);
assert(result == SL_RESULT_SUCCESS);
Khi tôi muốn chơi mẫu, tôi đang sử dụng:
Sample *sample = &samples[sampleNum];
// THIS WORKS FOR SIMPLY PLAYING THE SAMPLE, BUT I WANT THE BUFFER DIRECTLY
// if (sample->fdPlayerPlay != NULL) {
// // set the player's state to playing
// (*(sample->fdPlayerPlay))->SetPlayState(sample->fdPlayerPlay, SL_PLAYSTATE_PLAYING);
// }
// fill buffer with the samples from the file descriptor
(*(sample->fdBufferQueue))->Enqueue(sample->fdBufferQueue, sample->buffer,sample->totalSamples*sizeof(short));
// write the buffer to the outputBufferQueue, which is already playing
(*(sample->outputBufferQueue))->Enqueue(sample->outputBufferQueue, sample->buffer, sample->totalSamples*sizeof(short));
Tuy nhiên, điều này gây ra ứng dụng của tôi để đóng băng và đóng cửa. Có vài điều sai sót ở đây. Cũng, tôi không muốn lấy mẫu từ BufferQueue của Bộ mô tả tệp mỗi lần. Thay vào đó, tôi muốn lưu trữ vĩnh viễn nó trong một mảng byte, và Enqueue rằng đầu ra bất cứ khi nào tôi muốn.
Xin chào khiner, nó sẽ giúp bạn đọc .wav- tệp từ thư mục nội dung trong một byte Java hoặc mảng ngắn và sau đó xử lý thêm? –
Không chắc tôi có thể giúp được bao nhiêu, nhưng chỉ để ghi lại - bạn có đang sử dụng NDK không? Đó có phải là lý do tại sao mã của bạn trong C++? – Erhannis
Có, tôi đang sử dụng NDK, và điều này thực sự là tinh khiết C. Câu hỏi này là nhận được lâu trong răng. Tôi đã thực hiện tấn tiến bộ về điều này và sẽ nhận được xung quanh để thêm một câu trả lời khá. – khiner