Mercurial > almixer_isolated
comparison ALmixer.c @ 42:05e5dc4817a4
Warning: Breaking API/ABI changes. New optimizations to decouple update loop from number of buffers queued in audio streaming to allow more for more and smaller buffers to be processed in a loop. This also has the benefit for access_data callback buffer sizes not to be dictated by the performance tuning.
Note that the Load APIs break and add a new parameter to specify the target number of buffers to queue per update pass. Also, I changed the access_data from ALboolean to ALuint for possible future use since I'm already breaking the API. The motivation for this is for the feature request of allowing for data callbacks on buffer queue to modify the input data right before submission.
author | Eric Wing <ewing@anscamobile.com> |
---|---|
date | Tue, 30 Aug 2011 19:42:31 -0700 |
parents | e10dd3056782 |
children | 56855942fdc6 |
comparison
equal
deleted
inserted
replaced
41:e10dd3056782 | 42:05e5dc4817a4 |
---|---|
59 /* SDL_sound keeps a private linked list of sounds which get auto-deleted | 59 /* SDL_sound keeps a private linked list of sounds which get auto-deleted |
60 * on Sound_Quit. This might actually create some leaks for me in certain | 60 * on Sound_Quit. This might actually create some leaks for me in certain |
61 * usage patterns. To be safe, I should do the same. | 61 * usage patterns. To be safe, I should do the same. |
62 */ | 62 */ |
63 #include "LinkedList.h" | 63 #include "LinkedList.h" |
64 | |
65 #ifdef ANDROID_NDK | |
66 #undef fprintf | |
67 #include <android/log.h> | |
68 #define fprintf(stderr, ...) __android_log_print(ANDROID_LOG_INFO, "ALmixer", __VA_ARGS__) | |
69 #endif | |
70 | |
64 | 71 |
65 #ifdef ENABLE_ALMIXER_THREADS | 72 #ifdef ENABLE_ALMIXER_THREADS |
66 /* Needed for the Mutex locks (and threads if enabled) */ | 73 /* Needed for the Mutex locks (and threads if enabled) */ |
67 #ifdef ALMIXER_COMPILE_WITHOUT_SDL | 74 #ifdef ALMIXER_COMPILE_WITHOUT_SDL |
68 #include "SimpleMutex.h" | 75 #include "SimpleMutex.h" |
5464 * except when there is looping | 5471 * except when there is looping |
5465 */ | 5472 */ |
5466 | 5473 |
5467 /* NEW FEATURE: Try to queue up more buffers per pass, allowing the size of the buffer to be decoupled. */ | 5474 /* NEW FEATURE: Try to queue up more buffers per pass, allowing the size of the buffer to be decoupled. */ |
5468 /* TODO: Optimization: If number of available buffers (max_buffers-buffers_in_use), adjust the number of buffers to queue for this pass. */ | 5475 /* TODO: Optimization: If number of available buffers (max_buffers-buffers_in_use), adjust the number of buffers to queue for this pass. */ |
5476 /* I would benefit from a clearer flag that tells me whether we're in an underrun. | |
5477 * I think current_buffer only works if data callbacks are enabled. | |
5478 * So I'll look at for AL_STOPPED which might give me false positives, depending on the code above. | |
5479 * But I think/hope the code below will deal with it correctly. | |
5480 * If in an underrun, queue up at least startup_buffers. | |
5481 */ | |
5482 if(AL_STOPPED == state) | |
5483 { | |
5484 number_of_buffers_to_queue_this_pass = ALmixer_Channel_List[i].almixer_data->num_startup_buffers; | |
5485 // fprintf(stderr, "assuming underrun condition, using num_startup_buffers=%d\n", number_of_buffers_to_queue_this_pass); | |
5486 } | |
5487 | |
5488 /* Don't bother to check to make sure the number_of_buffers_to_queue_this_pass does not exceed the maximum number of buffers because of the logic hack bug. */ | |
5489 /* Logic Hack/Bug: In adding the number_of_buffers_to_queue_this_pass, I discovered the for-loop needs to be more decoupled. | |
5490 * The loop still needs to be entered because unqueuing and completion callbacks and possibly other state processing are also done. | |
5491 * So we always need to claim to queue one buffer. (The code already checks for max_queue_buffers.) | |
5492 */ | |
5493 if(0 == number_of_buffers_to_queue_this_pass) | |
5494 { | |
5495 number_of_buffers_to_queue_this_pass = 1; | |
5496 } | |
5469 for(current_count_of_buffer_queue_passes=0; current_count_of_buffer_queue_passes<number_of_buffers_to_queue_this_pass; current_count_of_buffer_queue_passes++) | 5497 for(current_count_of_buffer_queue_passes=0; current_count_of_buffer_queue_passes<number_of_buffers_to_queue_this_pass; current_count_of_buffer_queue_passes++) |
5470 { | 5498 { |
5471 | 5499 // fprintf(stderr, "current_count_of_buffer_queue_passes:%d\n", current_count_of_buffer_queue_passes); |
5472 /* For this to work, we must rely on EVERYTHING | 5500 |
5473 * else to unset the EOF if there is looping. | 5501 /* For this to work, we must rely on EVERYTHING |
5474 * Remember, even Play() must do this | 5502 * else to unset the EOF if there is looping. |
5475 */ | 5503 * Remember, even Play() must do this |
5476 | |
5477 /* If not EOF, then we are still playing. | |
5478 * Inside, we might find num_of_buffers < NUM...QUEUE_BUF.. | |
5479 * or buffers_process > 0 | |
5480 * in which case we queue up. | |
5481 * We also might find no buffers we need to fill, | |
5482 * in which case we just keep going | |
5483 */ | |
5484 if( ! ALmixer_Channel_List[i].almixer_data->eof) | |
5485 { | |
5486 ALuint bytes_returned; | |
5487 /* We have a priority. We first must assign | |
5488 * unused buffers in reserve. If there is nothing | |
5489 * left, then we may unqueue buffers. We can't | |
5490 * do it the other way around because we will | |
5491 * lose the pointer to the unqueued buffer | |
5492 */ | 5504 */ |
5493 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | 5505 |
5494 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | 5506 /* If not EOF, then we are still playing. |
5495 { | 5507 * Inside, we might find num_of_buffers < NUM...QUEUE_BUF.. |
5496 #if 0 | 5508 * or buffers_process > 0 |
5497 fprintf(stderr, "Getting more data in NOT_EOF and num_buffers_in_use (%d) < max_queue (%d)\n", | 5509 * in which case we queue up. |
5498 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use, | 5510 * We also might find no buffers we need to fill, |
5499 ALmixer_Channel_List[i].almixer_data->max_queue_buffers); | 5511 * in which case we just keep going |
5500 #endif | 5512 */ |
5501 /* Going to add an unused packet. | 5513 if( ! ALmixer_Channel_List[i].almixer_data->eof) |
5502 * Grab next packet */ | 5514 { |
5503 bytes_returned = GetMoreData( | 5515 ALuint bytes_returned; |
5504 ALmixer_Channel_List[i].almixer_data, | 5516 /* We have a priority. We first must assign |
5505 ALmixer_Channel_List[i].almixer_data->buffer[ | 5517 * unused buffers in reserve. If there is nothing |
5506 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | 5518 * left, then we may unqueue buffers. We can't |
5519 * do it the other way around because we will | |
5520 * lose the pointer to the unqueued buffer | |
5521 */ | |
5522 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | |
5523 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | |
5524 { | |
5525 #if 0 | |
5526 fprintf(stderr, "Getting more data in NOT_EOF and num_buffers_in_use (%d) < max_queue (%d)\n", | |
5527 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use, | |
5528 ALmixer_Channel_List[i].almixer_data->max_queue_buffers); | |
5529 #endif | |
5530 /* Going to add an unused packet. | |
5531 * Grab next packet */ | |
5532 bytes_returned = GetMoreData( | |
5533 ALmixer_Channel_List[i].almixer_data, | |
5534 ALmixer_Channel_List[i].almixer_data->buffer[ | |
5535 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | |
5536 ); | |
5537 } | |
5538 /* For processed > 0 */ | |
5539 else if(buffers_processed > 0) | |
5540 { | |
5541 /* Unqueue only 1 buffer for now. | |
5542 * If there are more than one, | |
5543 * let the next Update pass deal with it | |
5544 * so we don't stall the program for too long. | |
5545 */ | |
5546 #if 0 | |
5547 fprintf(stderr, "About to Unqueue, Buffers processed = %d\n", buffers_processed); | |
5548 fprintf(stderr, "Buffers queued= %d\n", buffers_still_queued); | |
5549 fprintf(stderr, "Unqueuing a buffer\n"); | |
5550 #endif | |
5551 alSourceUnqueueBuffers( | |
5552 ALmixer_Channel_List[i].alsource, | |
5553 1, &unqueued_buffer_id | |
5507 ); | 5554 ); |
5508 } | 5555 if((error = alGetError()) != AL_NO_ERROR) |
5509 /* For processed > 0 */ | 5556 { |
5510 else if(buffers_processed > 0) | 5557 fprintf(stderr, "Error with unqueue: %s, buffer id is %d", |
5511 { | 5558 alGetString(error), unqueued_buffer_id); |
5512 /* Unqueue only 1 buffer for now. | 5559 ALmixer_SetError("Unqueue buffer failed: %s", |
5513 * If there are more than one, | 5560 alGetString(error) ); |
5514 * let the next Update pass deal with it | 5561 error_flag--; |
5515 * so we don't stall the program for too long. | 5562 } |
5563 /* | |
5564 fprintf(stderr, "Right after unqueue..."); | |
5565 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
5566 fprintf(stderr, "Getting more data for NOT_EOF, max_buffers filled\n"); | |
5567 */ | |
5568 /* Grab unqueued packet */ | |
5569 bytes_returned = GetMoreData( | |
5570 ALmixer_Channel_List[i].almixer_data, | |
5571 unqueued_buffer_id); | |
5572 } | |
5573 /* We are still streaming, but currently | |
5574 * don't need to fill any buffers */ | |
5575 else | |
5576 { | |
5577 /* Might want to check state */ | |
5578 /* In case the playback stopped, | |
5579 * we need to resume | |
5580 * a.k.a. buffer underrun | |
5581 */ | |
5582 #if 1 | |
5583 /* Try not refetching the state here because I'm getting a duplicate | |
5584 buffer playback (hiccup) */ | |
5585 alGetSourcei( | |
5586 ALmixer_Channel_List[i].alsource, | |
5587 AL_SOURCE_STATE, &state | |
5588 ); | |
5589 if((error = alGetError()) != AL_NO_ERROR) | |
5590 { | |
5591 fprintf(stderr, "54bTesting error: %s\n", | |
5592 alGetString(error)); | |
5593 } | |
5594 /* Get the number of buffers processed | |
5595 */ | |
5596 alGetSourcei( | |
5597 ALmixer_Channel_List[i].alsource, | |
5598 AL_BUFFERS_PROCESSED, | |
5599 &buffers_processed | |
5600 ); | |
5601 if((error = alGetError()) != AL_NO_ERROR) | |
5602 { | |
5603 fprintf(stderr, "54cError, Can't get buffers_processed: %s\n", | |
5604 alGetString(error)); | |
5605 } | |
5606 #endif | |
5607 if(AL_STOPPED == state) | |
5608 { | |
5609 /* Resuming in not eof, but nothing to buffer */ | |
5610 | |
5611 /* Okay, here's another lately discovered problem: | |
5612 * I can't find it in the spec, but for at least some of the | |
5613 * implementations, if I call play on a stopped source that | |
5614 * has processed buffers, all those buffers get marked as unprocessed | |
5615 * on alSourcePlay. So if I had a queue of 25 with 24 of the buffers | |
5616 * processed, on resume, the earlier 24 buffers will get replayed, | |
5617 * causing a "hiccup" like sound in the playback. | |
5618 * To avoid this, I must unqueue all processed buffers before | |
5619 * calling play. But to complicate things, I need to worry about resyncing | |
5620 * the circular queue with this since I designed this thing | |
5621 * with some correlation between the two. However, I might | |
5622 * have already handled this, so I will try writing this code without | |
5623 * syncing for now. | |
5624 * There is currently an assumption that a buffer | |
5625 * was queued above so I actually have something | |
5626 * to play. | |
5627 */ | |
5628 ALint temp_count; | |
5629 #if 0 | |
5630 fprintf(stderr, "STOPPED1, need to clear processed=%d, status is:\n", buffers_processed); | |
5631 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
5632 #endif | |
5633 for(temp_count=0; temp_count<buffers_processed; temp_count++) | |
5634 { | |
5635 alSourceUnqueueBuffers( | |
5636 ALmixer_Channel_List[i].alsource, | |
5637 1, &unqueued_buffer_id | |
5638 ); | |
5639 if((error = alGetError()) != AL_NO_ERROR) | |
5640 { | |
5641 fprintf(stderr, "55aTesting error: %s\n", | |
5642 alGetString(error)); | |
5643 error_flag--; | |
5644 } | |
5645 } | |
5646 #if 0 | |
5647 fprintf(stderr, "After unqueue clear...:\n"); | |
5648 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
5649 #endif | |
5650 /* My assertion: We are STOPPED but not EOF. | |
5651 * This means we have a buffer underrun. | |
5652 * We just cleared out the unqueued buffers. | |
5653 * So we need to reset the mixer_data to reflect we have | |
5654 * no buffers in queue. | |
5655 * We need to GetMoreData and then queue up the data. | |
5656 * Then we need to resume playing. | |
5657 */ | |
5658 #if 0 | |
5659 int buffers_queued; | |
5660 alGetSourcei( | |
5661 ALmixer_Channel_List[i].alsource, | |
5662 AL_BUFFERS_QUEUED, | |
5663 &buffers_queued | |
5664 ); | |
5665 | |
5666 if((error = alGetError()) != AL_NO_ERROR) | |
5667 { | |
5668 fprintf(stderr, "Error in PrintQueueStatus, Can't get buffers_queued: %s\n", | |
5669 alGetString(error)); | |
5670 } | |
5671 assert(buffers_queued == 0); | |
5672 fprintf(stderr, "buffer underrun: buffers_queued:%d\n", buffers_queued); | |
5673 #endif | |
5674 | |
5675 /* Reset the number of buffers in use to 0 */ | |
5676 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use = 0; | |
5677 | |
5678 /* Get more data and put it in the first buffer */ | |
5679 bytes_returned = GetMoreData( | |
5680 ALmixer_Channel_List[i].almixer_data, | |
5681 ALmixer_Channel_List[i].almixer_data->buffer[0] | |
5682 ); | |
5683 /* NOTE: We might want to look for EOF and handle it here. | |
5684 * Currently, I just let the next loop handle it which seems to be working. | |
5685 */ | |
5686 if(bytes_returned > 0) | |
5687 { | |
5688 /* Queue up the new data */ | |
5689 alSourceQueueBuffers( | |
5690 ALmixer_Channel_List[i].alsource, | |
5691 1, | |
5692 &ALmixer_Channel_List[i].almixer_data->buffer[0] | |
5693 ); | |
5694 if((error = alGetError()) != AL_NO_ERROR) | |
5695 { | |
5696 fprintf(stderr, "56e alSourceQueueBuffers error: %s\n", | |
5697 alGetString(error)); | |
5698 } | |
5699 /* Increment the number of buffers in use */ | |
5700 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use++; | |
5701 | |
5702 | |
5703 /* We need to empty and update the circular buffer queue if it is in use */ | |
5704 if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL) | |
5705 { | |
5706 ALuint queue_ret_flag; | |
5707 CircularQueueUnsignedInt_Clear(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue); | |
5708 queue_ret_flag = CircularQueueUnsignedInt_PushBack( | |
5709 ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, | |
5710 ALmixer_Channel_List[i].almixer_data->buffer[0] | |
5711 ); | |
5712 if(0 == queue_ret_flag) | |
5713 { | |
5714 fprintf(stderr, "56fSerious internal error: CircularQueue could not push into queue.\n"); | |
5715 ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue"); | |
5716 } | |
5717 } | |
5718 | |
5719 | |
5720 | |
5721 | |
5722 /* Resume playback from underrun */ | |
5723 alSourcePlay(ALmixer_Channel_List[i].alsource); | |
5724 if((error = alGetError()) != AL_NO_ERROR) | |
5725 { | |
5726 fprintf(stderr, "55Tbesting error: %s\n", | |
5727 alGetString(error)); | |
5728 } | |
5729 } | |
5730 | |
5731 } | |
5732 /* Let's escape to the next loop. | |
5733 * All code below this point is for queuing up | |
5734 */ | |
5735 /* | |
5736 fprintf(stderr, "Entry: Nothing to do...continue\n\n"); | |
5737 */ | |
5738 continue; | |
5739 } | |
5740 /* We now know we have to fill an available | |
5741 * buffer. | |
5516 */ | 5742 */ |
5517 #if 0 | 5743 |
5518 fprintf(stderr, "About to Unqueue, Buffers processed = %d\n", buffers_processed); | 5744 /* In the previous branch, we just grabbed more data. |
5519 fprintf(stderr, "Buffers queued= %d\n", buffers_still_queued); | 5745 * Let's check it to make sure it's okay, |
5520 fprintf(stderr, "Unqueuing a buffer\n"); | 5746 * and then queue it up |
5521 #endif | 5747 */ |
5522 alSourceUnqueueBuffers( | 5748 /* This check doesn't work anymore because it is now ALuint */ |
5523 ALmixer_Channel_List[i].alsource, | 5749 #if 0 |
5524 1, &unqueued_buffer_id | 5750 if(-1 == bytes_returned) |
5525 ); | |
5526 if((error = alGetError()) != AL_NO_ERROR) | |
5527 { | 5751 { |
5528 fprintf(stderr, "Error with unqueue: %s", | 5752 /* Problem occurred...not sure what to do */ |
5529 alGetString(error)); | 5753 /* Go to next loop? */ |
5530 ALmixer_SetError("Unqueue buffer failed: %s", | |
5531 alGetString(error) ); | |
5532 error_flag--; | 5754 error_flag--; |
5755 /* Set the eof flag to force a quit so | |
5756 * we don't get stuck in an infinite loop | |
5757 */ | |
5758 ALmixer_Channel_List[i].almixer_data->eof = 1; | |
5759 continue; | |
5533 } | 5760 } |
5534 /* | 5761 #endif |
5535 fprintf(stderr, "Right after unqueue..."); | 5762 /* This is a special case where we've run |
5536 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | 5763 * out of data. We should check for loops |
5537 fprintf(stderr, "Getting more data for NOT_EOF, max_buffers filled\n"); | 5764 * and get more data. If there is no loop, |
5538 */ | 5765 * then do nothing and wait for future |
5539 /* Grab unqueued packet */ | 5766 * update passes to handle the EOF. |
5540 bytes_returned = GetMoreData( | 5767 * The advantage of handling the loop here |
5541 ALmixer_Channel_List[i].almixer_data, | 5768 * instead of waiting for play to stop is |
5542 unqueued_buffer_id); | 5769 * that we should be able to keep the buffer |
5543 } | 5770 * filled. |
5544 /* We are still streaming, but currently | 5771 */ |
5545 * don't need to fill any buffers */ | 5772 #if 0 |
5546 else | 5773 else if(0 == bytes_returned) |
5547 { | 5774 #endif |
5775 if(0 == bytes_returned) | |
5776 { | |
5777 /* | |
5778 fprintf(stderr, "We got 0 bytes from reading. Checking for loops\n"); | |
5779 */ | |
5780 /* Check for loops */ | |
5781 if( ALmixer_Channel_List[i].loops != 0 ) | |
5782 { | |
5783 /* We have to loop, so rewind | |
5784 * and fetch more data | |
5785 */ | |
5786 /* | |
5787 fprintf(stderr, "Rewinding data\n"); | |
5788 */ | |
5789 if(0 == Sound_Rewind( | |
5790 ALmixer_Channel_List[i].almixer_data->sample)) | |
5791 { | |
5792 fprintf(stderr, "Rewinding failed\n"); | |
5793 ALmixer_SetError( Sound_GetError() ); | |
5794 ALmixer_Channel_List[i].loops = 0; | |
5795 error_flag--; | |
5796 /* We'll continue on because we do have some valid data */ | |
5797 continue; | |
5798 } | |
5799 /* Remember to reset the data->eof flag */ | |
5800 ALmixer_Channel_List[i].almixer_data->eof = 0; | |
5801 if(ALmixer_Channel_List[i].loops > 0) | |
5802 { | |
5803 ALmixer_Channel_List[i].loops--; | |
5804 } | |
5805 /* Try grabbing another packet now. | |
5806 * Since we may have already unqueued a | |
5807 * buffer, we don't want to lose it. | |
5808 */ | |
5809 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | |
5810 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | |
5811 { | |
5812 /* | |
5813 fprintf(stderr, "We got %d bytes from reading loop. Filling unused packet\n", bytes_returned); | |
5814 */ | |
5815 /* Grab next packet */ | |
5816 bytes_returned = GetMoreData( | |
5817 ALmixer_Channel_List[i].almixer_data, | |
5818 ALmixer_Channel_List[i].almixer_data->buffer[ | |
5819 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | |
5820 ); | |
5821 /* | |
5822 fprintf(stderr, "We reread %d bytes into unused packet\n", bytes_returned); | |
5823 */ | |
5824 } | |
5825 /* Refilling unqueued packet */ | |
5826 else | |
5827 { | |
5828 /* | |
5829 fprintf(stderr, "We got %d bytes from reading loop. Filling unqueued packet\n", bytes_returned); | |
5830 */ | |
5831 /* Grab next packet */ | |
5832 bytes_returned = GetMoreData( | |
5833 ALmixer_Channel_List[i].almixer_data, | |
5834 unqueued_buffer_id); | |
5835 /* | |
5836 fprintf(stderr, "We reread %d bytes into unqueued packet\n", bytes_returned); | |
5837 */ | |
5838 } | |
5839 /* Another error check */ | |
5840 /* | |
5841 if(bytes_returned <= 0) | |
5842 */ | |
5843 if(0 == bytes_returned) | |
5844 { | |
5845 fprintf(stderr, "??????????ERROR\n"); | |
5846 ALmixer_SetError("Could not loop because after rewind, no data could be retrieved"); | |
5847 /* Problem occurred...not sure what to do */ | |
5848 /* Go to next loop? */ | |
5849 error_flag--; | |
5850 /* Set the eof flag to force a quit so | |
5851 * we don't get stuck in an infinite loop | |
5852 */ | |
5853 ALmixer_Channel_List[i].almixer_data->eof = 1; | |
5854 continue; | |
5855 } | |
5856 /* We made it to the end. We still need | |
5857 * to BufferData, so let this branch | |
5858 * fall into the next piece of | |
5859 * code below which will handle that | |
5860 */ | |
5861 | |
5862 | |
5863 } /* END loop check */ | |
5864 else | |
5865 { | |
5866 /* No more loops to do. | |
5867 * EOF flag should be set. | |
5868 * Just go to next loop and | |
5869 * let things be handled correctly | |
5870 * in future update calls | |
5871 */ | |
5872 /* | |
5873 fprintf(stderr, "SHOULD BE EOF\n"); | |
5874 | |
5875 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
5876 */ | |
5877 continue; | |
5878 } | |
5879 } /* END if bytes_returned == 0 */ | |
5880 /********* Possible trouble point. I might be queueing empty buffers on the mac. | |
5881 * This check doesn't say if the buffer is valid. Only the EOF assumption is a clue at this point | |
5882 */ | |
5883 /* Fall here */ | |
5884 /* Everything is normal. We aren't | |
5885 * at an EOF, but need to simply | |
5886 * queue more data. The data is already checked for good, | |
5887 * so queue it up */ | |
5888 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | |
5889 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | |
5890 { | |
5891 /* Keep count of how many buffers we have | |
5892 * to queue so we can return the value | |
5893 */ | |
5894 retval++; | |
5895 /* | |
5896 fprintf(stderr, "NOT_EOF???, about to Queue more data for num_buffers (%d) < max_queue (%d)\n", | |
5897 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use, | |
5898 ALmixer_Channel_List[i].almixer_data->max_queue_buffers); | |
5899 */ | |
5900 alSourceQueueBuffers( | |
5901 ALmixer_Channel_List[i].alsource, | |
5902 1, | |
5903 &ALmixer_Channel_List[i].almixer_data->buffer[ | |
5904 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | |
5905 ); | |
5906 if((error = alGetError()) != AL_NO_ERROR) | |
5907 { | |
5908 fprintf(stderr, "56Testing error: %s\n", | |
5909 alGetString(error)); | |
5910 } | |
5911 /* This is part of the hideous Nvidia workaround. In order to figure out | |
5912 * which buffer to show during callbacks (for things like | |
5913 * o-scopes), I must keep a copy of the buffers that are queued in my own | |
5914 * data structure. This code will be called only if | |
5915 * "access_data" was set, indicated by whether the queue is NULL. | |
5916 */ | |
5917 if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL) | |
5918 { | |
5919 ALuint queue_ret_flag; | |
5920 // fprintf(stderr, "56d: CircularQueue_PushBack.\n"); | |
5921 queue_ret_flag = CircularQueueUnsignedInt_PushBack( | |
5922 ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, | |
5923 ALmixer_Channel_List[i].almixer_data->buffer[ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | |
5924 ); | |
5925 if(0 == queue_ret_flag) | |
5926 { | |
5927 fprintf(stderr, "56aSerious internal error: CircularQueue could not push into queue.\n"); | |
5928 ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue"); | |
5929 } | |
5930 /* | |
5931 else | |
5932 { | |
5933 CircularQueueUnsignedInt_Print(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue); | |
5934 } | |
5935 */ | |
5936 } | |
5937 } | |
5938 /* for processed > 0 */ | |
5939 else | |
5940 { | |
5941 /* Keep count of how many buffers we have | |
5942 * to queue so we can return the value | |
5943 */ | |
5944 retval++; | |
5945 /* | |
5946 fprintf(stderr, "NOT_EOF, about to Queue more data for filled max_queue (%d)\n", | |
5947 ALmixer_Channel_List[i].almixer_data->max_queue_buffers); | |
5948 */ | |
5949 alSourceQueueBuffers( | |
5950 ALmixer_Channel_List[i].alsource, | |
5951 1, &unqueued_buffer_id); | |
5952 if((error = alGetError()) != AL_NO_ERROR) | |
5953 { | |
5954 ALmixer_SetError("Could not QueueBuffer: %s", | |
5955 alGetString(error) ); | |
5956 error_flag--; | |
5957 continue; | |
5958 } | |
5959 /* This is part of the hideous Nvidia workaround. In order to figure out | |
5960 * which buffer to show during callbacks (for things like | |
5961 * o-scopes), I must keep a copy of the buffers that are queued in my own | |
5962 * data structure. This code will be called only if | |
5963 * "access_data" was set, indicated by whether the queue is NULL. | |
5964 */ | |
5965 if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL) | |
5966 { | |
5967 ALuint queue_ret_flag; | |
5968 // fprintf(stderr, "56e: CircularQueue_PushBack.\n"); | |
5969 queue_ret_flag = CircularQueueUnsignedInt_PushBack( | |
5970 ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, | |
5971 unqueued_buffer_id | |
5972 ); | |
5973 if(0 == queue_ret_flag) | |
5974 { | |
5975 fprintf(stderr, "56bSerious internal error: CircularQueue could not push into queue.\n"); | |
5976 ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue"); | |
5977 } | |
5978 #if 0 | |
5979 else | |
5980 { | |
5981 CircularQueueUnsignedInt_Print(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue); | |
5982 } | |
5983 #endif | |
5984 } | |
5985 } | |
5986 /* If we used an available buffer queue, | |
5987 * then we need to update the number of them in use | |
5988 */ | |
5989 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | |
5990 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | |
5991 { | |
5992 /* Increment the number of buffers in use */ | |
5993 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use++; | |
5994 } | |
5548 /* Might want to check state */ | 5995 /* Might want to check state */ |
5549 /* In case the playback stopped, | 5996 /* In case the playback stopped, |
5550 * we need to resume | 5997 * we need to resume */ |
5551 * a.k.a. buffer underrun | |
5552 */ | |
5553 #if 1 | 5998 #if 1 |
5554 /* Try not refetching the state here because I'm getting a duplicate | 5999 /* Try not refetching the state here because I'm getting a duplicate |
5555 buffer playback (hiccup) */ | 6000 buffer playback (hiccup) */ |
5556 alGetSourcei( | 6001 alGetSourcei( |
5557 ALmixer_Channel_List[i].alsource, | 6002 ALmixer_Channel_List[i].alsource, |
5558 AL_SOURCE_STATE, &state | 6003 AL_SOURCE_STATE, &state |
5559 ); | 6004 ); |
5560 if((error = alGetError()) != AL_NO_ERROR) | 6005 if((error = alGetError()) != AL_NO_ERROR) |
5561 { | 6006 { |
5562 fprintf(stderr, "54bTesting error: %s\n", | 6007 fprintf(stderr, "57bTesting error: %s\n", |
5563 alGetString(error)); | 6008 alGetString(error)); |
5564 } | 6009 } |
5565 /* Get the number of buffers processed | 6010 /* Get the number of buffers processed |
5566 */ | 6011 */ |
5567 alGetSourcei( | 6012 alGetSourcei( |
5569 AL_BUFFERS_PROCESSED, | 6014 AL_BUFFERS_PROCESSED, |
5570 &buffers_processed | 6015 &buffers_processed |
5571 ); | 6016 ); |
5572 if((error = alGetError()) != AL_NO_ERROR) | 6017 if((error = alGetError()) != AL_NO_ERROR) |
5573 { | 6018 { |
5574 fprintf(stderr, "54cError, Can't get buffers_processed: %s\n", | 6019 fprintf(stderr, "57cError, Can't get buffers_processed: %s\n", |
5575 alGetString(error)); | 6020 alGetString(error)); |
5576 } | 6021 } |
5577 #endif | 6022 #endif |
5578 if(AL_STOPPED == state) | 6023 if(AL_STOPPED == state) |
5579 { | 6024 { |
5580 /* Resuming in not eof, but nothing to buffer */ | 6025 /* |
5581 | 6026 fprintf(stderr, "Resuming in not eof\n"); |
5582 /* Okay, here's another lately discovered problem: | 6027 */ |
5583 * I can't find it in the spec, but for at least some of the | 6028 /* Okay, here's another lately discovered problem: |
5584 * implementations, if I call play on a stopped source that | 6029 * I can't find it in the spec, but for at least some of the |
5585 * has processed buffers, all those buffers get marked as unprocessed | 6030 * implementations, if I call play on a stopped source that |
5586 * on alSourcePlay. So if I had a queue of 25 with 24 of the buffers | 6031 * has processed buffers, all those buffers get marked as unprocessed |
5587 * processed, on resume, the earlier 24 buffers will get replayed, | 6032 * on alSourcePlay. So if I had a queue of 25 with 24 of the buffers |
5588 * causing a "hiccup" like sound in the playback. | 6033 * processed, on resume, the earlier 24 buffers will get replayed, |
5589 * To avoid this, I must unqueue all processed buffers before | 6034 * causing a "hiccup" like sound in the playback. |
5590 * calling play. But to complicate things, I need to worry about resyncing | 6035 * To avoid this, I must unqueue all processed buffers before |
5591 * the circular queue with this since I designed this thing | 6036 * calling play. But to complicate things, I need to worry about resyncing |
5592 * with some correlation between the two. However, I might | 6037 * the circular queue with this since I designed this thing |
5593 * have already handled this, so I will try writing this code without | 6038 * with some correlation between the two. However, I might |
5594 * syncing for now. | 6039 * have already handled this, so I will try writing this code without |
5595 * There is currently an assumption that a buffer | 6040 * syncing for now. |
5596 * was queued above so I actually have something | 6041 * There is currently an assumption that a buffer |
5597 * to play. | 6042 * was queued above so I actually have something |
6043 * to play. | |
6044 */ | |
6045 ALint temp_count; | |
6046 /* | |
6047 fprintf(stderr, "STOPPED2, need to clear processed, status is:\n"); | |
6048 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
6049 */ | |
6050 | |
6051 for(temp_count=0; temp_count<buffers_processed; temp_count++) | |
6052 { | |
6053 alSourceUnqueueBuffers( | |
6054 ALmixer_Channel_List[i].alsource, | |
6055 1, &unqueued_buffer_id | |
6056 ); | |
6057 if((error = alGetError()) != AL_NO_ERROR) | |
6058 { | |
6059 fprintf(stderr, "58aTesting error: %s\n", | |
6060 alGetString(error)); | |
6061 error_flag--; | |
6062 } | |
6063 } | |
6064 /* | |
6065 fprintf(stderr, "After unqueue clear...:\n"); | |
6066 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
6067 */ | |
6068 | |
6069 alSourcePlay(ALmixer_Channel_List[i].alsource); | |
6070 if((error = alGetError()) != AL_NO_ERROR) | |
6071 { | |
6072 fprintf(stderr, "55Tbesting 8rror: %s\n", | |
6073 alGetString(error)); | |
6074 } | |
6075 } | |
6076 continue; | |
6077 } /* END if( ! eof) */ | |
6078 /* We have hit EOF in the SDL_Sound sample and there | |
6079 * are no more loops. However, there may still be | |
6080 * buffers in the OpenAL queue which still need to | |
6081 * be played out. The following body of code will | |
6082 * determine if play is still happening or | |
6083 * initiate the stop/cleanup sequenece. | |
6084 */ | |
6085 else | |
6086 { | |
6087 /* Let's continue to remove the used up | |
6088 * buffers as they come in. */ | |
6089 if(buffers_processed > 0) | |
6090 { | |
6091 ALint temp_count; | |
6092 /* Do as a for-loop because I don't want | |
6093 * to have to create an array for the | |
6094 * unqueued_buffer_id's | |
5598 */ | 6095 */ |
5599 ALint temp_count; | |
5600 #if 0 | |
5601 fprintf(stderr, "STOPPED1, need to clear processed=%d, status is:\n", buffers_processed); | |
5602 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
5603 #endif | |
5604 for(temp_count=0; temp_count<buffers_processed; temp_count++) | 6096 for(temp_count=0; temp_count<buffers_processed; temp_count++) |
5605 { | 6097 { |
6098 /* | |
6099 fprintf(stderr, "unqueuing remainder, %d\n", temp_count); | |
6100 */ | |
5606 alSourceUnqueueBuffers( | 6101 alSourceUnqueueBuffers( |
5607 ALmixer_Channel_List[i].alsource, | 6102 ALmixer_Channel_List[i].alsource, |
5608 1, &unqueued_buffer_id | 6103 1, &unqueued_buffer_id |
5609 ); | 6104 ); |
5610 if((error = alGetError()) != AL_NO_ERROR) | 6105 if((error = alGetError()) != AL_NO_ERROR) |
5611 { | 6106 { |
5612 fprintf(stderr, "55aTesting error: %s\n", | 6107 fprintf(stderr, "59Testing error: %s\n", |
5613 alGetString(error)); | 6108 alGetString(error)); |
5614 error_flag--; | |
5615 } | 6109 } |
5616 } | 6110 } |
5617 #if 0 | 6111 /* |
5618 fprintf(stderr, "After unqueue clear...:\n"); | 6112 fprintf(stderr, "done unqueuing remainder for this loop, %d\n", temp_count); |
5619 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | 6113 */ |
5620 #endif | 6114 |
5621 /* My assertion: We are STOPPED but not EOF. | 6115 /* Need to update counts since we removed everything. |
5622 * This means we have a buffer underrun. | 6116 * If we don't update the counts here, we end up in the |
5623 * We just cleared out the unqueued buffers. | 6117 * "Shouldn't be here section, but maybe it's okay due to race conditions" |
5624 * So we need to reset the mixer_data to reflect we have | |
5625 * no buffers in queue. | |
5626 * We need to GetMoreData and then queue up the data. | |
5627 * Then we need to resume playing. | |
5628 */ | 6118 */ |
5629 #if 0 | |
5630 int buffers_queued; | |
5631 alGetSourcei( | 6119 alGetSourcei( |
5632 ALmixer_Channel_List[i].alsource, | 6120 ALmixer_Channel_List[i].alsource, |
5633 AL_BUFFERS_QUEUED, | 6121 AL_BUFFERS_QUEUED, &buffers_still_queued |
5634 &buffers_queued | |
5635 ); | 6122 ); |
5636 | |
5637 if((error = alGetError()) != AL_NO_ERROR) | 6123 if((error = alGetError()) != AL_NO_ERROR) |
5638 { | 6124 { |
5639 fprintf(stderr, "Error in PrintQueueStatus, Can't get buffers_queued: %s\n", | 6125 fprintf(stderr, "5100Testing error: %s\n", |
5640 alGetString(error)); | 6126 alGetString(error)); |
5641 } | |
5642 assert(buffers_queued == 0); | |
5643 fprintf(stderr, "buffer underrun: buffers_queued:%d\n", buffers_queued); | |
5644 #endif | |
5645 | |
5646 /* Reset the number of buffers in use to 0 */ | |
5647 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use = 0; | |
5648 | |
5649 /* Get more data and put it in the first buffer */ | |
5650 bytes_returned = GetMoreData( | |
5651 ALmixer_Channel_List[i].almixer_data, | |
5652 ALmixer_Channel_List[i].almixer_data->buffer[0] | |
5653 ); | |
5654 /* NOTE: We might want to look for EOF and handle it here. | |
5655 * Currently, I just let the next loop handle it which seems to be working. | |
5656 */ | |
5657 if(bytes_returned > 0) | |
5658 { | |
5659 /* Queue up the new data */ | |
5660 alSourceQueueBuffers( | |
5661 ALmixer_Channel_List[i].alsource, | |
5662 1, | |
5663 &ALmixer_Channel_List[i].almixer_data->buffer[0] | |
5664 ); | |
5665 if((error = alGetError()) != AL_NO_ERROR) | |
5666 { | |
5667 fprintf(stderr, "56e alSourceQueueBuffers error: %s\n", | |
5668 alGetString(error)); | |
5669 } | |
5670 /* Increment the number of buffers in use */ | |
5671 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use++; | |
5672 | |
5673 | |
5674 /* We need to empty and update the circular buffer queue if it is in use */ | |
5675 if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL) | |
5676 { | |
5677 ALuint queue_ret_flag; | |
5678 CircularQueueUnsignedInt_Clear(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue); | |
5679 queue_ret_flag = CircularQueueUnsignedInt_PushBack( | |
5680 ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, | |
5681 ALmixer_Channel_List[i].almixer_data->buffer[0] | |
5682 ); | |
5683 if(0 == queue_ret_flag) | |
5684 { | |
5685 fprintf(stderr, "56fSerious internal error: CircularQueue could not push into queue.\n"); | |
5686 ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue"); | |
5687 } | |
5688 } | |
5689 | |
5690 | |
5691 | |
5692 | |
5693 /* Resume playback from underrun */ | |
5694 alSourcePlay(ALmixer_Channel_List[i].alsource); | |
5695 if((error = alGetError()) != AL_NO_ERROR) | |
5696 { | |
5697 fprintf(stderr, "55Tbesting error: %s\n", | |
5698 alGetString(error)); | |
5699 } | |
5700 } | 6127 } |
5701 | 6128 /* Get the number of buffers processed |
5702 } | 6129 * so we know if we need to refill |
5703 /* Let's escape to the next loop. | 6130 */ |
5704 * All code below this point is for queuing up | 6131 alGetSourcei( |
5705 */ | 6132 ALmixer_Channel_List[i].alsource, |
5706 /* | 6133 AL_BUFFERS_PROCESSED, &buffers_processed |
5707 fprintf(stderr, "Entry: Nothing to do...continue\n\n"); | 6134 ); |
5708 */ | |
5709 continue; | |
5710 } | |
5711 /* We now know we have to fill an available | |
5712 * buffer. | |
5713 */ | |
5714 | |
5715 /* In the previous branch, we just grabbed more data. | |
5716 * Let's check it to make sure it's okay, | |
5717 * and then queue it up | |
5718 */ | |
5719 /* This check doesn't work anymore because it is now ALuint */ | |
5720 #if 0 | |
5721 if(-1 == bytes_returned) | |
5722 { | |
5723 /* Problem occurred...not sure what to do */ | |
5724 /* Go to next loop? */ | |
5725 error_flag--; | |
5726 /* Set the eof flag to force a quit so | |
5727 * we don't get stuck in an infinite loop | |
5728 */ | |
5729 ALmixer_Channel_List[i].almixer_data->eof = 1; | |
5730 continue; | |
5731 } | |
5732 #endif | |
5733 /* This is a special case where we've run | |
5734 * out of data. We should check for loops | |
5735 * and get more data. If there is no loop, | |
5736 * then do nothing and wait for future | |
5737 * update passes to handle the EOF. | |
5738 * The advantage of handling the loop here | |
5739 * instead of waiting for play to stop is | |
5740 * that we should be able to keep the buffer | |
5741 * filled. | |
5742 */ | |
5743 #if 0 | |
5744 else if(0 == bytes_returned) | |
5745 #endif | |
5746 if(0 == bytes_returned) | |
5747 { | |
5748 /* | |
5749 fprintf(stderr, "We got 0 bytes from reading. Checking for loops\n"); | |
5750 */ | |
5751 /* Check for loops */ | |
5752 if( ALmixer_Channel_List[i].loops != 0 ) | |
5753 { | |
5754 /* We have to loop, so rewind | |
5755 * and fetch more data | |
5756 */ | |
5757 /* | |
5758 fprintf(stderr, "Rewinding data\n"); | |
5759 */ | |
5760 if(0 == Sound_Rewind( | |
5761 ALmixer_Channel_List[i].almixer_data->sample)) | |
5762 { | |
5763 fprintf(stderr, "Rewinding failed\n"); | |
5764 ALmixer_SetError( Sound_GetError() ); | |
5765 ALmixer_Channel_List[i].loops = 0; | |
5766 error_flag--; | |
5767 /* We'll continue on because we do have some valid data */ | |
5768 continue; | |
5769 } | |
5770 /* Remember to reset the data->eof flag */ | |
5771 ALmixer_Channel_List[i].almixer_data->eof = 0; | |
5772 if(ALmixer_Channel_List[i].loops > 0) | |
5773 { | |
5774 ALmixer_Channel_List[i].loops--; | |
5775 } | |
5776 /* Try grabbing another packet now. | |
5777 * Since we may have already unqueued a | |
5778 * buffer, we don't want to lose it. | |
5779 */ | |
5780 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | |
5781 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | |
5782 { | |
5783 /* | |
5784 fprintf(stderr, "We got %d bytes from reading loop. Filling unused packet\n", bytes_returned); | |
5785 */ | |
5786 /* Grab next packet */ | |
5787 bytes_returned = GetMoreData( | |
5788 ALmixer_Channel_List[i].almixer_data, | |
5789 ALmixer_Channel_List[i].almixer_data->buffer[ | |
5790 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | |
5791 ); | |
5792 /* | |
5793 fprintf(stderr, "We reread %d bytes into unused packet\n", bytes_returned); | |
5794 */ | |
5795 } | |
5796 /* Refilling unqueued packet */ | |
5797 else | |
5798 { | |
5799 /* | |
5800 fprintf(stderr, "We got %d bytes from reading loop. Filling unqueued packet\n", bytes_returned); | |
5801 */ | |
5802 /* Grab next packet */ | |
5803 bytes_returned = GetMoreData( | |
5804 ALmixer_Channel_List[i].almixer_data, | |
5805 unqueued_buffer_id); | |
5806 /* | |
5807 fprintf(stderr, "We reread %d bytes into unqueued packet\n", bytes_returned); | |
5808 */ | |
5809 } | |
5810 /* Another error check */ | |
5811 /* | |
5812 if(bytes_returned <= 0) | |
5813 */ | |
5814 if(0 == bytes_returned) | |
5815 { | |
5816 fprintf(stderr, "??????????ERROR\n"); | |
5817 ALmixer_SetError("Could not loop because after rewind, no data could be retrieved"); | |
5818 /* Problem occurred...not sure what to do */ | |
5819 /* Go to next loop? */ | |
5820 error_flag--; | |
5821 /* Set the eof flag to force a quit so | |
5822 * we don't get stuck in an infinite loop | |
5823 */ | |
5824 ALmixer_Channel_List[i].almixer_data->eof = 1; | |
5825 continue; | |
5826 } | |
5827 /* We made it to the end. We still need | |
5828 * to BufferData, so let this branch | |
5829 * fall into the next piece of | |
5830 * code below which will handle that | |
5831 */ | |
5832 | |
5833 | |
5834 } /* END loop check */ | |
5835 else | |
5836 { | |
5837 /* No more loops to do. | |
5838 * EOF flag should be set. | |
5839 * Just go to next loop and | |
5840 * let things be handled correctly | |
5841 * in future update calls | |
5842 */ | |
5843 /* | |
5844 fprintf(stderr, "SHOULD BE EOF\n"); | |
5845 | |
5846 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
5847 */ | |
5848 continue; | |
5849 } | |
5850 } /* END if bytes_returned == 0 */ | |
5851 /********* Possible trouble point. I might be queueing empty buffers on the mac. | |
5852 * This check doesn't say if the buffer is valid. Only the EOF assumption is a clue at this point | |
5853 */ | |
5854 /* Fall here */ | |
5855 /* Everything is normal. We aren't | |
5856 * at an EOF, but need to simply | |
5857 * queue more data. The data is already checked for good, | |
5858 * so queue it up */ | |
5859 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | |
5860 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | |
5861 { | |
5862 /* Keep count of how many buffers we have | |
5863 * to queue so we can return the value | |
5864 */ | |
5865 retval++; | |
5866 /* | |
5867 fprintf(stderr, "NOT_EOF???, about to Queue more data for num_buffers (%d) < max_queue (%d)\n", | |
5868 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use, | |
5869 ALmixer_Channel_List[i].almixer_data->max_queue_buffers); | |
5870 */ | |
5871 alSourceQueueBuffers( | |
5872 ALmixer_Channel_List[i].alsource, | |
5873 1, | |
5874 &ALmixer_Channel_List[i].almixer_data->buffer[ | |
5875 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | |
5876 ); | |
5877 if((error = alGetError()) != AL_NO_ERROR) | |
5878 { | |
5879 fprintf(stderr, "56Testing error: %s\n", | |
5880 alGetString(error)); | |
5881 } | |
5882 /* This is part of the hideous Nvidia workaround. In order to figure out | |
5883 * which buffer to show during callbacks (for things like | |
5884 * o-scopes), I must keep a copy of the buffers that are queued in my own | |
5885 * data structure. This code will be called only if | |
5886 * "access_data" was set, indicated by whether the queue is NULL. | |
5887 */ | |
5888 if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL) | |
5889 { | |
5890 ALuint queue_ret_flag; | |
5891 // fprintf(stderr, "56d: CircularQueue_PushBack.\n"); | |
5892 queue_ret_flag = CircularQueueUnsignedInt_PushBack( | |
5893 ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, | |
5894 ALmixer_Channel_List[i].almixer_data->buffer[ALmixer_Channel_List[i].almixer_data->num_buffers_in_use] | |
5895 ); | |
5896 if(0 == queue_ret_flag) | |
5897 { | |
5898 fprintf(stderr, "56aSerious internal error: CircularQueue could not push into queue.\n"); | |
5899 ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue"); | |
5900 } | |
5901 /* | |
5902 else | |
5903 { | |
5904 CircularQueueUnsignedInt_Print(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue); | |
5905 } | |
5906 */ | |
5907 } | |
5908 } | |
5909 /* for processed > 0 */ | |
5910 else | |
5911 { | |
5912 /* Keep count of how many buffers we have | |
5913 * to queue so we can return the value | |
5914 */ | |
5915 retval++; | |
5916 /* | |
5917 fprintf(stderr, "NOT_EOF, about to Queue more data for filled max_queue (%d)\n", | |
5918 ALmixer_Channel_List[i].almixer_data->max_queue_buffers); | |
5919 */ | |
5920 alSourceQueueBuffers( | |
5921 ALmixer_Channel_List[i].alsource, | |
5922 1, &unqueued_buffer_id); | |
5923 if((error = alGetError()) != AL_NO_ERROR) | |
5924 { | |
5925 ALmixer_SetError("Could not QueueBuffer: %s", | |
5926 alGetString(error) ); | |
5927 error_flag--; | |
5928 continue; | |
5929 } | |
5930 /* This is part of the hideous Nvidia workaround. In order to figure out | |
5931 * which buffer to show during callbacks (for things like | |
5932 * o-scopes), I must keep a copy of the buffers that are queued in my own | |
5933 * data structure. This code will be called only if | |
5934 * "access_data" was set, indicated by whether the queue is NULL. | |
5935 */ | |
5936 if(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue != NULL) | |
5937 { | |
5938 ALuint queue_ret_flag; | |
5939 // fprintf(stderr, "56e: CircularQueue_PushBack.\n"); | |
5940 queue_ret_flag = CircularQueueUnsignedInt_PushBack( | |
5941 ALmixer_Channel_List[i].almixer_data->circular_buffer_queue, | |
5942 unqueued_buffer_id | |
5943 ); | |
5944 if(0 == queue_ret_flag) | |
5945 { | |
5946 fprintf(stderr, "56bSerious internal error: CircularQueue could not push into queue.\n"); | |
5947 ALmixer_SetError("Serious internal error: CircularQueue failed to push into queue"); | |
5948 } | |
5949 #if 0 | |
5950 else | |
5951 { | |
5952 CircularQueueUnsignedInt_Print(ALmixer_Channel_List[i].almixer_data->circular_buffer_queue); | |
5953 } | |
5954 #endif | |
5955 } | |
5956 } | |
5957 /* If we used an available buffer queue, | |
5958 * then we need to update the number of them in use | |
5959 */ | |
5960 if(ALmixer_Channel_List[i].almixer_data->num_buffers_in_use | |
5961 < ALmixer_Channel_List[i].almixer_data->max_queue_buffers) | |
5962 { | |
5963 /* Increment the number of buffers in use */ | |
5964 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use++; | |
5965 } | |
5966 /* Might want to check state */ | |
5967 /* In case the playback stopped, | |
5968 * we need to resume */ | |
5969 #if 1 | |
5970 /* Try not refetching the state here because I'm getting a duplicate | |
5971 buffer playback (hiccup) */ | |
5972 alGetSourcei( | |
5973 ALmixer_Channel_List[i].alsource, | |
5974 AL_SOURCE_STATE, &state | |
5975 ); | |
5976 if((error = alGetError()) != AL_NO_ERROR) | |
5977 { | |
5978 fprintf(stderr, "57bTesting error: %s\n", | |
5979 alGetString(error)); | |
5980 } | |
5981 /* Get the number of buffers processed | |
5982 */ | |
5983 alGetSourcei( | |
5984 ALmixer_Channel_List[i].alsource, | |
5985 AL_BUFFERS_PROCESSED, | |
5986 &buffers_processed | |
5987 ); | |
5988 if((error = alGetError()) != AL_NO_ERROR) | |
5989 { | |
5990 fprintf(stderr, "57cError, Can't get buffers_processed: %s\n", | |
5991 alGetString(error)); | |
5992 } | |
5993 #endif | |
5994 if(AL_STOPPED == state) | |
5995 { | |
5996 /* | |
5997 fprintf(stderr, "Resuming in not eof\n"); | |
5998 */ | |
5999 /* Okay, here's another lately discovered problem: | |
6000 * I can't find it in the spec, but for at least some of the | |
6001 * implementations, if I call play on a stopped source that | |
6002 * has processed buffers, all those buffers get marked as unprocessed | |
6003 * on alSourcePlay. So if I had a queue of 25 with 24 of the buffers | |
6004 * processed, on resume, the earlier 24 buffers will get replayed, | |
6005 * causing a "hiccup" like sound in the playback. | |
6006 * To avoid this, I must unqueue all processed buffers before | |
6007 * calling play. But to complicate things, I need to worry about resyncing | |
6008 * the circular queue with this since I designed this thing | |
6009 * with some correlation between the two. However, I might | |
6010 * have already handled this, so I will try writing this code without | |
6011 * syncing for now. | |
6012 * There is currently an assumption that a buffer | |
6013 * was queued above so I actually have something | |
6014 * to play. | |
6015 */ | |
6016 ALint temp_count; | |
6017 /* | |
6018 fprintf(stderr, "STOPPED2, need to clear processed, status is:\n"); | |
6019 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
6020 */ | |
6021 | |
6022 for(temp_count=0; temp_count<buffers_processed; temp_count++) | |
6023 { | |
6024 alSourceUnqueueBuffers( | |
6025 ALmixer_Channel_List[i].alsource, | |
6026 1, &unqueued_buffer_id | |
6027 ); | |
6028 if((error = alGetError()) != AL_NO_ERROR) | |
6029 { | |
6030 fprintf(stderr, "58aTesting error: %s\n", | |
6031 alGetString(error)); | |
6032 error_flag--; | |
6033 } | |
6034 } | |
6035 /* | |
6036 fprintf(stderr, "After unqueue clear...:\n"); | |
6037 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
6038 */ | |
6039 | |
6040 alSourcePlay(ALmixer_Channel_List[i].alsource); | |
6041 if((error = alGetError()) != AL_NO_ERROR) | 6135 if((error = alGetError()) != AL_NO_ERROR) |
6042 { | 6136 { |
6043 fprintf(stderr, "55Tbesting 8rror: %s\n", | 6137 fprintf(stderr, "5200Testing error: %s\n", |
6044 alGetString(error)); | |
6045 } | |
6046 } | |
6047 continue; | |
6048 } /* END if( ! eof) */ | |
6049 /* We have hit EOF in the SDL_Sound sample and there | |
6050 * are no more loops. However, there may still be | |
6051 * buffers in the OpenAL queue which still need to | |
6052 * be played out. The following body of code will | |
6053 * determine if play is still happening or | |
6054 * initiate the stop/cleanup sequenece. | |
6055 */ | |
6056 else | |
6057 { | |
6058 /* Let's continue to remove the used up | |
6059 * buffers as they come in. */ | |
6060 if(buffers_processed > 0) | |
6061 { | |
6062 ALint temp_count; | |
6063 /* Do as a for-loop because I don't want | |
6064 * to have to create an array for the | |
6065 * unqueued_buffer_id's | |
6066 */ | |
6067 for(temp_count=0; temp_count<buffers_processed; temp_count++) | |
6068 { | |
6069 /* | |
6070 fprintf(stderr, "unqueuing remainder, %d\n", temp_count); | |
6071 */ | |
6072 alSourceUnqueueBuffers( | |
6073 ALmixer_Channel_List[i].alsource, | |
6074 1, &unqueued_buffer_id | |
6075 ); | |
6076 if((error = alGetError()) != AL_NO_ERROR) | |
6077 { | |
6078 fprintf(stderr, "59Testing error: %s\n", | |
6079 alGetString(error)); | 6138 alGetString(error)); |
6080 } | 6139 } |
6081 } | 6140 } |
6082 /* | 6141 |
6083 fprintf(stderr, "done unqueuing remainder for this loop, %d\n", temp_count); | 6142 |
6084 */ | 6143 /* Else if buffers_processed == 0 |
6085 | 6144 * and buffers_still_queued == 0. |
6086 /* Need to update counts since we removed everything. | 6145 * then we check to see if the source |
6087 * If we don't update the counts here, we end up in the | 6146 * is still playing. Quit if stopped |
6088 * "Shouldn't be here section, but maybe it's okay due to race conditions" | 6147 * We shouldn't need to worry about |
6148 * looping because that should have | |
6149 * been handled above. | |
6089 */ | 6150 */ |
6090 alGetSourcei( | 6151 if(0 == buffers_still_queued) |
6091 ALmixer_Channel_List[i].alsource, | |
6092 AL_BUFFERS_QUEUED, &buffers_still_queued | |
6093 ); | |
6094 if((error = alGetError()) != AL_NO_ERROR) | |
6095 { | 6152 { |
6096 fprintf(stderr, "5100Testing error: %s\n", | 6153 /* Make sure playback has stopped before |
6097 alGetString(error)); | 6154 * we shutdown. |
6098 } | 6155 */ |
6099 /* Get the number of buffers processed | 6156 alGetSourcei( |
6100 * so we know if we need to refill | 6157 ALmixer_Channel_List[i].alsource, |
6101 */ | 6158 AL_SOURCE_STATE, &state |
6102 alGetSourcei( | 6159 ); |
6103 ALmixer_Channel_List[i].alsource, | 6160 if((error = alGetError()) != AL_NO_ERROR) |
6104 AL_BUFFERS_PROCESSED, &buffers_processed | 6161 { |
6105 ); | 6162 fprintf(stderr, "60Testing error: %s\n", |
6106 if((error = alGetError()) != AL_NO_ERROR) | 6163 alGetString(error)); |
6164 } | |
6165 if(AL_STOPPED == state) | |
6166 { | |
6167 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use = 0; | |
6168 /* Playback has ended. | |
6169 * Loop if necessary, or launch callback | |
6170 * and clear channel (or clear channel and | |
6171 * then launch callback?) | |
6172 * Update: Need to do callback first because I reference the mixer_data and source | |
6173 */ | |
6174 | |
6175 /* Launch callback */ | |
6176 Invoke_Channel_Done_Callback(i, AL_TRUE); | |
6177 | |
6178 Clean_Channel(i); | |
6179 /* Subtract counter */ | |
6180 Is_Playing_global--; | |
6181 | |
6182 | |
6183 /* We're done for this loop. | |
6184 * Go to next channel | |
6185 */ | |
6186 | |
6187 /* I used to call continue here, but continue isn't safe anymore because we are in the number_of_queue_buffers_per_pass loop now. | |
6188 * We should break, but we need to be careful that there is no code that is run once we break that wasn't run before. | |
6189 * We want to make sure we go immediately to the next iteration in the channel loop. | |
6190 */ | |
6191 break; | |
6192 } | |
6193 } /* End end-playback */ | |
6194 else | |
6107 { | 6195 { |
6108 fprintf(stderr, "5200Testing error: %s\n", | 6196 /* Need to run out buffer */ |
6109 alGetString(error)); | 6197 #if 1 |
6110 } | 6198 /* Might want to check state */ |
6111 } | 6199 /* In case the playback stopped, |
6112 | 6200 * we need to resume */ |
6113 | 6201 alGetSourcei( |
6114 /* Else if buffers_processed == 0 | 6202 ALmixer_Channel_List[i].alsource, |
6115 * and buffers_still_queued == 0. | 6203 AL_SOURCE_STATE, &state |
6116 * then we check to see if the source | 6204 ); |
6117 * is still playing. Quit if stopped | 6205 if((error = alGetError()) != AL_NO_ERROR) |
6118 * We shouldn't need to worry about | 6206 { |
6119 * looping because that should have | 6207 fprintf(stderr, "61Testing error: %s\n", |
6120 * been handled above. | 6208 alGetString(error)); |
6121 */ | 6209 } |
6122 if(0 == buffers_still_queued) | 6210 if(AL_STOPPED == state) |
6123 { | 6211 { |
6124 /* Make sure playback has stopped before | 6212 /* |
6125 * we shutdown. | 6213 fprintf(stderr, "Shouldn't be here. %d Buffers still in queue, but play stopped. This might be correct though because race conditions could have caused the STOP to happen right after our other tests...Checking queue status...\n", buffers_still_queued); |
6126 */ | 6214 */ |
6127 alGetSourcei( | 6215 /* |
6128 ALmixer_Channel_List[i].alsource, | 6216 PrintQueueStatus(ALmixer_Channel_List[i].alsource); |
6129 AL_SOURCE_STATE, &state | 6217 */ |
6130 ); | 6218 /* Rather than force unqueuing the buffer, let's see if |
6131 if((error = alGetError()) != AL_NO_ERROR) | 6219 * setting the buffer to none works (the OpenAL 1.0 |
6132 { | 6220 * Reference Annotation suggests this should work). |
6133 fprintf(stderr, "60Testing error: %s\n", | 6221 */ |
6134 alGetString(error)); | 6222 alSourcei(ALmixer_Channel_List[i].alsource, |
6135 } | 6223 AL_BUFFER, AL_NONE); |
6136 if(AL_STOPPED == state) | 6224 /* |
6137 { | 6225 PrintQueueStatus(ALmixer_Channel_List[i].alsource); |
6138 ALmixer_Channel_List[i].almixer_data->num_buffers_in_use = 0; | 6226 */ |
6139 /* Playback has ended. | 6227 /* This doesn't work because in some cases, I think |
6140 * Loop if necessary, or launch callback | 6228 * it causes the sound to be replayed |
6141 * and clear channel (or clear channel and | 6229 */ |
6142 * then launch callback?) | 6230 /* |
6143 * Update: Need to do callback first because I reference the mixer_data and source | 6231 fprintf(stderr, "Resuming in eof (trying to run out buffers\n"); |
6144 */ | 6232 alSourcePlay(ALmixer_Channel_List[i].alsource); |
6145 | 6233 */ |
6146 /* Launch callback */ | 6234 } |
6147 Invoke_Channel_Done_Callback(i, AL_TRUE); | 6235 #endif |
6148 | 6236 } /* End trap section */ |
6149 Clean_Channel(i); | 6237 } /* End POST-EOF use-up buffer section */ |
6150 /* Subtract counter */ | 6238 |
6151 Is_Playing_global--; | 6239 } /* END NEW number of queue buffers per pass */ |
6152 | |
6153 | |
6154 /* We're done for this loop. | |
6155 * Go to next channel | |
6156 */ | |
6157 continue; | |
6158 } | |
6159 } /* End end-playback */ | |
6160 else | |
6161 { | |
6162 /* Need to run out buffer */ | |
6163 #if 1 | |
6164 /* Might want to check state */ | |
6165 /* In case the playback stopped, | |
6166 * we need to resume */ | |
6167 alGetSourcei( | |
6168 ALmixer_Channel_List[i].alsource, | |
6169 AL_SOURCE_STATE, &state | |
6170 ); | |
6171 if((error = alGetError()) != AL_NO_ERROR) | |
6172 { | |
6173 fprintf(stderr, "61Testing error: %s\n", | |
6174 alGetString(error)); | |
6175 } | |
6176 if(AL_STOPPED == state) | |
6177 { | |
6178 /* | |
6179 fprintf(stderr, "Shouldn't be here. %d Buffers still in queue, but play stopped. This might be correct though because race conditions could have caused the STOP to happen right after our other tests...Checking queue status...\n", buffers_still_queued); | |
6180 */ | |
6181 /* | |
6182 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
6183 */ | |
6184 /* Rather than force unqueuing the buffer, let's see if | |
6185 * setting the buffer to none works (the OpenAL 1.0 | |
6186 * Reference Annotation suggests this should work). | |
6187 */ | |
6188 alSourcei(ALmixer_Channel_List[i].alsource, | |
6189 AL_BUFFER, AL_NONE); | |
6190 /* | |
6191 PrintQueueStatus(ALmixer_Channel_List[i].alsource); | |
6192 */ | |
6193 /* This doesn't work because in some cases, I think | |
6194 * it causes the sound to be replayed | |
6195 */ | |
6196 /* | |
6197 fprintf(stderr, "Resuming in eof (trying to run out buffers\n"); | |
6198 alSourcePlay(ALmixer_Channel_List[i].alsource); | |
6199 */ | |
6200 } | |
6201 #endif | |
6202 } /* End trap section */ | |
6203 } /* End POST-EOF use-up buffer section */ | |
6204 | |
6205 } /* END NEW number of queue buffers per pass */ | |
6206 | 6240 |
6207 } /* END Streamed section */ | 6241 } /* END Streamed section */ |
6208 } /* END channel in use */ | 6242 } /* END channel in use */ |
6209 } /* END for-loop for each channel */ | 6243 } /* END for-loop for each channel */ |
6210 | 6244 |
7827 } | 7861 } |
7828 | 7862 |
7829 | 7863 |
7830 | 7864 |
7831 | 7865 |
7832 static ALmixer_Data* DoLoad(Sound_Sample* sample, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data) | 7866 static ALmixer_Data* DoLoad(Sound_Sample* sample, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALuint suggested_number_of_buffers_to_queue_per_update_pass, ALuint access_data) |
7833 { | 7867 { |
7834 ALuint bytes_decoded; | 7868 ALuint bytes_decoded; |
7835 ALmixer_Data* ret_data; | 7869 ALmixer_Data* ret_data; |
7836 ALenum error; | 7870 ALenum error; |
7837 | 7871 |
7880 { | 7914 { |
7881 num_startup_buffers = max_queue_buffers; | 7915 num_startup_buffers = max_queue_buffers; |
7882 } | 7916 } |
7883 ret_data->num_startup_buffers = num_startup_buffers; | 7917 ret_data->num_startup_buffers = num_startup_buffers; |
7884 | 7918 |
7885 /* TODO: Expose value through public API */ | 7919 /* Set up the update pass buffers */ |
7886 ret_data->num_target_buffers_per_pass = 1; | 7920 if(0 == suggested_number_of_buffers_to_queue_per_update_pass) |
7921 { | |
7922 suggested_number_of_buffers_to_queue_per_update_pass = ALMIXER_DEFAULT_BUFFERS_TO_QUEUE_PER_UPDATE_PASS; | |
7923 } | |
7924 /* Make sure update pass up buffers is less or equal to max_queue_buffers */ | |
7925 if(suggested_number_of_buffers_to_queue_per_update_pass > max_queue_buffers) | |
7926 { | |
7927 suggested_number_of_buffers_to_queue_per_update_pass = max_queue_buffers; | |
7928 } | |
7929 ret_data->num_target_buffers_per_pass = suggested_number_of_buffers_to_queue_per_update_pass; | |
7887 | 7930 |
7888 ret_data->buffer_map_list = NULL; | 7931 ret_data->buffer_map_list = NULL; |
7889 ret_data->current_buffer = 0; | 7932 ret_data->current_buffer = 0; |
7890 | 7933 |
7891 ret_data->circular_buffer_queue = NULL; | 7934 ret_data->circular_buffer_queue = NULL; |
8375 * I don't like the AudioInfo parameter. I removed it once, | 8418 * I don't like the AudioInfo parameter. I removed it once, |
8376 * but the system will fail on RAW samples because the user | 8419 * but the system will fail on RAW samples because the user |
8377 * must specify it, so I had to bring it back. | 8420 * must specify it, so I had to bring it back. |
8378 * Remember I must close the rwops if there is an error before NewSample() | 8421 * Remember I must close the rwops if there is an error before NewSample() |
8379 */ | 8422 */ |
8380 ALmixer_Data* ALmixer_LoadSample_RW(ALmixer_RWops* rwops, const char* fileext, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data) | 8423 ALmixer_Data* ALmixer_LoadSample_RW(ALmixer_RWops* rwops, const char* fileext, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALuint suggested_number_of_buffers_to_queue_per_update_pass, ALuint access_data) |
8381 { | 8424 { |
8382 Sound_Sample* sample = NULL; | 8425 Sound_Sample* sample = NULL; |
8383 Sound_AudioInfo target; | 8426 Sound_AudioInfo target; |
8384 | 8427 |
8385 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) | 8428 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) |
8416 { | 8459 { |
8417 ALmixer_SetError(Sound_GetError()); | 8460 ALmixer_SetError(Sound_GetError()); |
8418 return NULL; | 8461 return NULL; |
8419 } | 8462 } |
8420 | 8463 |
8421 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data)); | 8464 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, suggested_number_of_buffers_to_queue_per_update_pass, access_data)); |
8422 } | 8465 } |
8423 | 8466 |
8424 | 8467 |
8425 | 8468 |
8426 /* This will load a sample for us from | 8469 /* This will load a sample for us from |
8427 * a file (instead of RWops). Most of the uglyness is | 8470 * a file (instead of RWops). Most of the uglyness is |
8428 * error checking and the fact that streamed/predecoded files | 8471 * error checking and the fact that streamed/predecoded files |
8429 * must be treated differently. | 8472 * must be treated differently. |
8430 */ | 8473 */ |
8431 ALmixer_Data* ALmixer_LoadSample(const char* filename, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data) | 8474 ALmixer_Data* ALmixer_LoadSample(const char* filename, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALuint suggested_number_of_buffers_to_queue_per_update_pass, ALuint access_data) |
8432 { | 8475 { |
8433 Sound_Sample* sample = NULL; | 8476 Sound_Sample* sample = NULL; |
8434 Sound_AudioInfo target; | 8477 Sound_AudioInfo target; |
8435 | 8478 |
8436 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) | 8479 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) |
8526 } | 8569 } |
8527 | 8570 |
8528 /* | 8571 /* |
8529 fprintf(stderr, "Correction test: Actual rate=%d, desired=%d, actual format=%d, desired format=%d\n", sample->actual.rate, sample->desired.rate, sample->actual.format, sample->desired.format); | 8572 fprintf(stderr, "Correction test: Actual rate=%d, desired=%d, actual format=%d, desired format=%d\n", sample->actual.rate, sample->desired.rate, sample->actual.format, sample->desired.format); |
8530 */ | 8573 */ |
8531 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data)); | 8574 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, suggested_number_of_buffers_to_queue_per_update_pass, access_data)); |
8532 } | 8575 } |
8533 | 8576 |
8534 | 8577 |
8535 /* This is a back door for RAW samples or if you need the | 8578 /* This is a back door for RAW samples or if you need the |
8536 * AudioInfo field. Use at your own risk. | 8579 * AudioInfo field. Use at your own risk. |
8537 */ | 8580 */ |
8538 ALmixer_Data* ALmixer_LoadSample_RAW_RW(ALmixer_RWops* rwops, const char* fileext, ALmixer_AudioInfo* desired, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data) | 8581 ALmixer_Data* ALmixer_LoadSample_RAW_RW(ALmixer_RWops* rwops, const char* fileext, ALmixer_AudioInfo* desired, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALuint suggested_number_of_buffers_to_queue_per_update_pass, ALuint access_data) |
8539 { | 8582 { |
8540 Sound_Sample* sample = NULL; | 8583 Sound_Sample* sample = NULL; |
8541 Sound_AudioInfo sound_desired; | 8584 Sound_AudioInfo sound_desired; |
8542 | 8585 |
8543 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) | 8586 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) |
8566 if(NULL == sample) | 8609 if(NULL == sample) |
8567 { | 8610 { |
8568 ALmixer_SetError(Sound_GetError()); | 8611 ALmixer_SetError(Sound_GetError()); |
8569 return NULL; | 8612 return NULL; |
8570 } | 8613 } |
8571 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data)); | 8614 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers,suggested_number_of_buffers_to_queue_per_update_pass, access_data)); |
8572 } | 8615 } |
8573 | 8616 |
8574 | 8617 |
8575 | 8618 |
8576 | 8619 |
8577 /* This is a back door for RAW samples or if you need the | 8620 /* This is a back door for RAW samples or if you need the |
8578 * AudioInfo field. Use at your own risk. | 8621 * AudioInfo field. Use at your own risk. |
8579 */ | 8622 */ |
8580 ALmixer_Data* ALmixer_LoadSample_RAW(const char* filename, ALmixer_AudioInfo* desired, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALboolean access_data) | 8623 ALmixer_Data* ALmixer_LoadSample_RAW(const char* filename, ALmixer_AudioInfo* desired, ALuint buffersize, ALboolean decode_mode_is_predecoded, ALuint max_queue_buffers, ALuint num_startup_buffers, ALuint suggested_number_of_buffers_to_queue_per_update_pass, ALuint access_data) |
8581 { | 8624 { |
8582 Sound_Sample* sample = NULL; | 8625 Sound_Sample* sample = NULL; |
8583 Sound_AudioInfo sound_desired; | 8626 Sound_AudioInfo sound_desired; |
8584 | 8627 |
8585 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) | 8628 if( (AL_FALSE == ALmixer_Initialized) || (AL_TRUE == g_inInterruption) ) |
8609 if(NULL == sample) | 8652 if(NULL == sample) |
8610 { | 8653 { |
8611 ALmixer_SetError(Sound_GetError()); | 8654 ALmixer_SetError(Sound_GetError()); |
8612 return NULL; | 8655 return NULL; |
8613 } | 8656 } |
8614 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data)); | 8657 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, suggested_number_of_buffers_to_queue_per_update_pass, access_data)); |
8615 } | 8658 } |
8616 | 8659 |
8617 | 8660 |
8618 void ALmixer_FreeData(ALmixer_Data* data) | 8661 void ALmixer_FreeData(ALmixer_Data* data) |
8619 { | 8662 { |