2010-04-07 27 views
11

Tôi đang viết ứng dụng khách máy tính để bàn từ xa cho iPhone và tôi đang cố triển khai chuyển hướng âm thanh.
Máy khách được kết nối với máy chủ qua kết nối ổ cắm và máy chủ gửi dữ liệu PCM 32K một lúc.Sử dụng Dịch vụ Hàng đợi Âm thanh để phát dữ liệu PCM qua kết nối ổ cắm

Tôi đang cố gắng sử dụng AQS để phát dữ liệu và phát hai giây đầu tiên (1 giá trị bộ đệm). Tuy nhiên, vì đoạn dữ liệu tiếp theo không đi qua ổ cắm, nên AudioQueueBuffer tiếp theo trống. Khi dữ liệu đến, tôi điền vào bộ đệm có sẵn tiếp theo với dữ liệu và đưa nó vào với AudioQueueEnqueueBuffer. Tuy nhiên, nó không bao giờ chơi các bộ đệm này.

Hàng đợi có ngừng phát nếu không có bộ đệm trong hàng đợi, ngay cả khi sau này bạn thêm bộ đệm?

Dưới đây là phần có liên quan của mã:

void 
wave_out_write(STREAM s, uint16 tick, uint8 index) 
{ 

    if(items_in_queue == NUM_BUFFERS){ 
     return; 
    } 
    if(!playState.busy){ 
     OSStatus status; 
     status = AudioQueueNewOutput(&playState.dataFormat, AudioOutputCallback, &playState, CFRunLoopGetCurrent(), NULL, 0, &playState.queue); 

     if(status == 0){ 
      for(int i=0; i<NUM_BUFFERS; i++){ 
       AudioQueueAllocateBuffer(playState.queue, 40000, &playState.buffers[i]); 

      } 
      AudioQueueAddPropertyListener(playState.queue, kAudioQueueProperty_IsRunning, MyAudioQueuePropertyListenerProc, &playState); 

      status = AudioQueueStart(playState.queue, NULL); 
      if(status ==0){ 
       playState.busy = True; 
      } 
      else{ 
       return; 
      } 
     } 
     else{ 
      return; 
     } 
    } 
    playState.buffers[queue_hi]->mAudioDataByteSize = s->size; 

    memcpy(playState.buffers[queue_hi]->mAudioData, s->data, s->size); 

    AudioQueueEnqueueBuffer(playState.queue, playState.buffers[queue_hi], 0, 0); 
    queue_hi++; 
    queue_hi = queue_hi % NUM_BUFFERS; 
    items_in_queue++; 
} 


void AudioOutputCallback(void* inUserData, AudioQueueRef outAQ, AudioQueueBufferRef outBuffer) 
{ 
    PlayState *playState = (PlayState *)inUserData; 
    items_in_queue--; 
} 

Cảm ơn!

Trả lời

0

Nói chung, khi sử dụng bộ đệm âm thanh tròn, bạn nên tránh các bộ đệm từ underrunning. Nếu bạn thiếu dữ liệu cần thiết (ví dụ: tắc nghẽn mạng), hãy cố gắng đệm dữ liệu âm thanh của bạn bằng cách tắt tiếng hoặc tạm dừng phát lại âm thanh.

Có thể là khi chuỗi bộ đệm của bạn bị hỏng, bạn cần phải khởi động lại phát lại. Tôi đã không bao giờ thực sự underrunned bộ đệm AudioQueue, nhưng tôi nhớ từ lập trình Win32 rằng đây là trường hợp, vì vậy xin vui lòng sửa tôi nếu tôi là sai.

+3

Bạn không cần phải dán bất kỳ thứ gì có sự im lặng. Nếu bạn không có bất kỳ dữ liệu nào để đưa trở lại hàng đợi khi gọi lại của bạn được gọi, chỉ cần không đặt bất kỳ dữ liệu nào ở đó. Nếu hàng đợi của bạn hết dữ liệu, nó sẽ tự phát âm thanh cho đến khi bạn enqueue dữ liệu một lần nữa. Nếu tất cả các bộ đệm nằm ngoài hàng đợi, hàm gọi lại của bạn không được gọi lại, nhưng bạn vẫn có thể enqueue dữ liệu vào hàng đợi từ một hàm khác không phải là hàm gọi lại (ví dụ: ngay khi dữ liệu đã đến). Đây không phải là vấn đề của người đăng. Vấn đề của anh ta là anh ta chỉ có một bộ đệm trong hàng đợi để bắt đầu. Bạn cần ít nhất 2. – Mecki

+0

Cảm ơn Mecki, tôi có một vấn đề tương tự, và mặc dù giải pháp chưa được viết ra, ít nhất là điểm này đi đúng hướng ... – Nick

1

Sử dụng các dịch vụ xếp hàng âm thanh của CoreAudio được đơn giản hóa rất nhiều bằng cách đảm bảo rằng bạn luôn xếp hàng lại mọi bộ đệm ngay sau khi phát lại xong bằng cách thực hiện trong cuộc gọi lại khi quá trình phát kết thúc. Dữ liệu âm thanh phải nằm trong bộ đệm tròn riêng biệt khi được nhận từ mạng sao cho mạng và mã âm thanh không được ghép trực tiếp.

Để đảm bảo bạn không thả âm thanh, hãy xếp hàng một số bộ đệm cố định với dữ liệu; điều này hoạt động như một bộ đệm jitter. Không bắt đầu phát lại cho đến khi tất cả các vùng đệm được xếp hàng đợi. Ngay sau khi mỗi bộ đệm phát xong, hãy xếp lại ngay lập tức với gói dữ liệu tiếp theo. Nếu không có dữ liệu, chỉ cần xếp hàng một bộ đệm của sự im lặng; kể từ khi các gói âm thanh đến cuối cùng sẽ bắt kịp, điều này chỉ có tác dụng giảm âm thanh bị giảm tại các chi phí của độ trễ thêm.

0

Tôi thấy thật ngu ngốc khi tôi có thể đăng câu trả lời nhưng không nhận xét ở đây nếu tôi không có đủ điểm. Tôi chỉ muốn thêm vào câu trả lời sau đây:

"Có thể là khi chuỗi bộ đệm của bạn bị hỏng, bạn cần phải khởi động lại. Tôi chưa bao giờ thực sự vượt qua bộ đệm AudioQueue, nhưng tôi nhớ từ lập trình Win32 rằng đây là trường hợp, vì vậy xin vui lòng sửa tôi nếu tôi sai. "

Tôi đã thực sự thử nghiệm kịch bản này trong trình phát âm thanh mà tôi đã tạo gần đây. Tôi đã thực hiện một bộ giải mã FLAC từ đầu, và nó hỗ trợ 16 bit bài hát chỉ vào lúc này. Nếu tôi vấp phải một bài hát có 24 bit, tôi tiếp tục mất đồng bộ với bài hát tôi đang chơi - nó sẽ không chơi chút nào - và có thể mất một khoảng thời gian, 30 giây để làm ví dụ, để phục hồi. Điều này khiến cho Hàng đợi Âm thanh thực sự tồi tệ và khi tôi bắt đầu gửi bộ đệm lần nữa đến hàng đợi âm thanh, phải mất 30 giây để bắt đầu bài hát tiếp theo để phát lại.

Đây chỉ là quan sát của tôi và tôi chưa suy nghĩ nhiều về lý do tại sao tôi quan sát hành vi này. Có lẽ nó ném đi mẫu để phù hợp với số lượng mẫu AudioQueue nghĩ rằng nó nên được chơi tại thời điểm này - rằng nó bị mất trong thời gian đói? Trình phát âm thanh của tôi dường như phát nhanh bài hát đến khi đạt đến điểm mà nó muốn phát lại.

CHỈNH SỬA: Miễn là bạn đăng bộ đệm mới cho mọi cuộc gọi lại, bạn sẽ không bao giờ phải khởi động lại lần phát hoặc bất kỳ thứ gì. Trong trình phát của tôi, nếu tôi không thực hiện xử lý bộ đệm khi bộ đệm tiếp theo được gọi là 'trở lại', luồng cho bộ đệm đó sẽ bị chặn cho đến khi bộ đệm đầu tiên được thực hiện xong. Điều này được thực hiện với NSLock. Đây là lý do chính AudioQueues bị đánh dấu nặng khi tôi mất đồng bộ khi người chơi của tôi chưa hiểu được FLAC 24 bit. NSLock cũng ngăn chặn bất kỳ điều kiện chủng tộc nào khi AudioQueue cung cấp cho bạn nhiều bộ đệm hơn để lấp đầy. Tôi sử dụng 3 bộ đệm với độ trễ thấp. Độ trễ quá thấp mang đến sự im lặng hoàn toàn, vì vậy bạn cần phải tìm một 'kích thước tốt' cho hệ thống của mình.

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