Mercurial > almixer_isolated
comparison ALmixer.c @ 43:a55e1f3d8f10
merged
author | Eric Wing <ewing@anscamobile.com> |
---|---|
date | Tue, 30 Aug 2011 19:43:49 -0700 |
parents | 05e5dc4817a4 |
children | 56855942fdc6 |
comparison
equal
deleted
inserted
replaced
40:2b0b55b7f8cf | 43:a55e1f3d8f10 |
---|---|
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 { |