@@ -196,9 +196,6 @@ OSWRAPPER_AUDIO_DEF size_t oswrapper_audio_get_samples(OSWrapper_audio_spec* aud
196196#ifndef OSWRAPPER_AUDIO_MEMCPY
197197#define OSWRAPPER_AUDIO_MEMCPY (x , y , amount ) memcpy(x, y, amount)
198198#endif /* OSWRAPPER_AUDIO_MEMCPY */
199- #ifndef OSWRAPPER_AUDIO_MEMMOVE
200- #define OSWRAPPER_AUDIO_MEMMOVE (x , y , amount ) memmove(x, y, amount)
201- #endif /* OSWRAPPER_AUDIO_MEMMOVE */
202199#ifndef OSWRAPPER_AUDIO_MEMCMP
203200#define OSWRAPPER_AUDIO_MEMCMP (ptr1 , ptr2 , amount ) memcmp(ptr1, ptr2, amount)
204201#endif /* OSWRAPPER_AUDIO_MEMCMP */
@@ -542,12 +539,6 @@ OSWRAPPER_AUDIO_DEF size_t oswrapper_audio_get_samples(OSWrapper_audio_spec* aud
542539#define OSWRAPPER_AUDIO__MF_STARTUP_VAL MFSTARTUP_LITE
543540#endif
544541
545- #ifndef OSWRAPPER_AUDIO__DEFAULT_INTERNAL_BUFFER_SIZE
546- /* TODO Not sure what a good size is for this.
547- This is the largest value I've seen on my system so far. */
548- #define OSWRAPPER_AUDIO__DEFAULT_INTERNAL_BUFFER_SIZE 0x84E0
549- #endif
550-
551542typedef struct oswrapper_audio__internal_data_win {
552543 IMFSourceReader * reader ;
553544 IMFByteStream * byte_stream ;
@@ -759,22 +750,16 @@ OSWRAPPER_AUDIO_DEF OSWRAPPER_AUDIO_RESULT_TYPE oswrapper_audio__load_from_reade
759750 oswrapper_audio__internal_data_win * internal_data = (oswrapper_audio__internal_data_win * ) OSWRAPPER_AUDIO_MALLOC (sizeof (oswrapper_audio__internal_data_win ));
760751
761752 if (internal_data != NULL ) {
762- short * initial_buffer = (short * ) OSWRAPPER_AUDIO_MALLOC (OSWRAPPER_AUDIO__DEFAULT_INTERNAL_BUFFER_SIZE * sizeof (short ));
763-
764- if (initial_buffer != NULL ) {
765- audio -> internal_data = (void * ) internal_data ;
766- internal_data -> reader = reader ;
767- internal_data -> byte_stream = byte_stream ;
768- internal_data -> memory_stream = memory_stream ;
769- internal_data -> internal_buffer = initial_buffer ;
770- internal_data -> internal_buffer_pos = 0 ;
771- internal_data -> internal_buffer_remaining = 0 ;
772- internal_data -> internal_buffer_size = OSWRAPPER_AUDIO__DEFAULT_INTERNAL_BUFFER_SIZE ;
773- internal_data -> no_reader_error = OSWRAPPER_AUDIO_RESULT_SUCCESS ;
774- return OSWRAPPER_AUDIO_RESULT_SUCCESS ;
775- }
776-
777- OSWRAPPER_AUDIO_FREE (internal_data );
753+ audio -> internal_data = (void * ) internal_data ;
754+ internal_data -> reader = reader ;
755+ internal_data -> byte_stream = byte_stream ;
756+ internal_data -> memory_stream = memory_stream ;
757+ internal_data -> internal_buffer = NULL ;
758+ internal_data -> internal_buffer_pos = 0 ;
759+ internal_data -> internal_buffer_remaining = 0 ;
760+ internal_data -> internal_buffer_size = 0 ;
761+ internal_data -> no_reader_error = OSWRAPPER_AUDIO_RESULT_SUCCESS ;
762+ return OSWRAPPER_AUDIO_RESULT_SUCCESS ;
778763 }
779764 }
780765
@@ -903,20 +888,25 @@ OSWRAPPER_AUDIO_DEF void oswrapper_audio_rewind(OSWrapper_audio_spec* audio) {
903888 internal_data -> internal_buffer_pos = 0 ;
904889}
905890
906- /* TODO This code isn't optimised. If you're brave enough, you can probably speed it up and save memory. */
907- static void oswrapper_audio__get_new_samples (OSWrapper_audio_spec * audio , size_t frames_to_do ) {
891+ OSWRAPPER_AUDIO_DEF size_t oswrapper_audio_get_samples (OSWrapper_audio_spec * audio , short * buffer , size_t frames_to_do ) {
892+ size_t frame_size ;
893+ size_t frames_done ;
908894 oswrapper_audio__internal_data_win * internal_data = (oswrapper_audio__internal_data_win * ) audio -> internal_data ;
909-
910- /* Move any remaining samples to the start of the buffer, if they're not at the start of the buffer */
911- if (internal_data -> internal_buffer_remaining > 0 && (internal_data -> internal_buffer_pos != 0 )) {
912- OSWRAPPER_AUDIO_MEMMOVE (internal_data -> internal_buffer , internal_data -> internal_buffer + internal_data -> internal_buffer_pos , internal_data -> internal_buffer_remaining * (sizeof internal_data -> internal_buffer [0 ]));
895+ frame_size = (audio -> bits_per_channel / 8 ) * audio -> channel_count ;
896+ frames_to_do = frames_to_do * frame_size / sizeof (short );
897+ frames_done = 0 ;
898+
899+ /* Copy any previous excess frames from the internal buffer */
900+ if (internal_data -> internal_buffer_remaining > 0 ) {
901+ size_t copied_sample_data_size = internal_data -> internal_buffer_remaining < frames_to_do ? internal_data -> internal_buffer_remaining : frames_to_do ;
902+ OSWRAPPER_AUDIO_MEMCPY (buffer , internal_data -> internal_buffer + internal_data -> internal_buffer_pos , copied_sample_data_size * (sizeof internal_data -> internal_buffer [0 ]));
903+ internal_data -> internal_buffer_remaining -= copied_sample_data_size ;
904+ internal_data -> internal_buffer_pos += copied_sample_data_size ;
905+ frames_done = copied_sample_data_size ;
913906 }
914907
915- /* Reset the buffer position to 0 */
916- internal_data -> internal_buffer_pos = 0 ;
917-
918908 /* Get new samples */
919- while (frames_to_do > internal_data -> internal_buffer_remaining ) {
909+ while (frames_to_do > frames_done ) {
920910 size_t new_target_frames = 0 ;
921911
922912 /* Check if IMFSourceReader methods can still be called */
@@ -946,33 +936,49 @@ static void oswrapper_audio__get_new_samples(OSWrapper_audio_spec* audio, size_t
946936 if (SUCCEEDED (result )) {
947937 size_t new_target_size ;
948938 new_target_frames = current_length / sizeof (short );
949- new_target_size = internal_data -> internal_buffer_remaining + new_target_frames ;
950-
951- if (new_target_size > internal_data -> internal_buffer_size ) {
952- /* Try to allocate enough memory to store the sample + the buffered samples */
953- short * realloc_buffer = (short * ) OSWRAPPER_AUDIO_MALLOC (new_target_size * sizeof (short ));
954-
955- if (realloc_buffer == NULL ) {
956- /* Couldn't allocate any more memory, just work with what we have */
957- new_target_frames = internal_data -> internal_buffer_size - internal_data -> internal_buffer_remaining ;
958- current_length = (DWORD ) (new_target_frames / sizeof (short ));
959- frames_to_do = internal_data -> internal_buffer_remaining + new_target_frames ;
960- } else {
961- /* Copy contents of the old buffer to the new buffer */
962- OSWRAPPER_AUDIO_MEMCPY (realloc_buffer , internal_data -> internal_buffer , internal_data -> internal_buffer_size );
963- /* Free old buffer */
964- OSWRAPPER_AUDIO_FREE (internal_data -> internal_buffer );
965- /* Replace old buffer with new buffer */
966- internal_data -> internal_buffer = realloc_buffer ;
967- internal_data -> internal_buffer_size = new_target_size ;
939+ new_target_size = frames_done + new_target_frames ;
940+
941+ /* If the size of the decoded sample would exceed the remaining buffer size,
942+ store the excess frames in the internal buffer */
943+ if (new_target_size > frames_to_do ) {
944+ size_t remaining_sample_data_size = new_target_size - frames_to_do ;
945+ /* Prevent copying more data to the output buffer than requested */
946+ new_target_frames -= remaining_sample_data_size ;
947+ current_length = (DWORD ) new_target_frames * sizeof (short );
948+
949+ /* Is the internal buffer large enough to store the excess frames? */
950+ if (internal_data -> internal_buffer_size < remaining_sample_data_size ) {
951+ /* Try to allocate enough memory to store the excess frames */
952+ short * realloc_buffer = (short * ) OSWRAPPER_AUDIO_MALLOC (remaining_sample_data_size * sizeof (short ));
953+
954+ if (realloc_buffer != NULL ) {
955+ /* Free old buffer */
956+ OSWRAPPER_AUDIO_FREE (internal_data -> internal_buffer );
957+ /* Replace old buffer with new buffer */
958+ internal_data -> internal_buffer = realloc_buffer ;
959+ internal_data -> internal_buffer_size = remaining_sample_data_size ;
960+ } else {
961+ /* If we can't allocate more memory, some excess frames will be lost.
962+ This is unlikely, and mostly harmless. */
963+ remaining_sample_data_size = internal_data -> internal_buffer_size ;
964+ }
965+ }
966+
967+ /* Copy as many excess frames as we have space for */
968+ internal_data -> internal_buffer_remaining = remaining_sample_data_size ;
969+ internal_data -> internal_buffer_pos = 0 ;
970+
971+ if (remaining_sample_data_size > 0 ) {
972+ OSWRAPPER_AUDIO_MEMCPY ((BYTE * )(internal_data -> internal_buffer ), sample_audio_data + current_length , remaining_sample_data_size * sizeof (short ));
968973 }
969974 }
970975
976+ /* Copy decoded sample data to buffer, minus excess frames */
971977 if (new_target_frames > 0 ) {
972- OSWRAPPER_AUDIO_MEMCPY ((BYTE * )(internal_data -> internal_buffer + internal_data -> internal_buffer_remaining ), sample_audio_data , current_length );
978+ OSWRAPPER_AUDIO_MEMCPY ((BYTE * )(buffer + frames_done ), sample_audio_data , current_length );
973979 }
974980
975- result = IMFMediaBuffer_Unlock (media_buffer );
981+ /* result = */ IMFMediaBuffer_Unlock (media_buffer );
976982 /* TODO I'm not sure there's any way to handle this?
977983 if (FAILED(result)) {
978984 ...some code?
@@ -992,35 +998,13 @@ static void oswrapper_audio__get_new_samples(OSWrapper_audio_spec* audio, size_t
992998
993999 if (new_target_frames == 0 ) {
9941000 /* Break the loop */
995- frames_to_do = internal_data -> internal_buffer_remaining ;
1001+ break ;
9961002 } else {
997- internal_data -> internal_buffer_remaining += new_target_frames ;
1003+ frames_done += new_target_frames ;
9981004 }
9991005 }
1000- }
1001-
1002- OSWRAPPER_AUDIO_DEF size_t oswrapper_audio_get_samples (OSWrapper_audio_spec * audio , short * buffer , size_t frames_to_do ) {
1003- size_t frame_size ;
1004- oswrapper_audio__internal_data_win * internal_data = (oswrapper_audio__internal_data_win * ) audio -> internal_data ;
1005- frame_size = (audio -> bits_per_channel / 8 ) * audio -> channel_count ;
1006-
1007- /* We have to buffer decoding ourselves due to API quirks */
1008- if (internal_data -> internal_buffer_remaining < (frames_to_do * frame_size / sizeof (short ))) {
1009- oswrapper_audio__get_new_samples (audio , frames_to_do * frame_size / sizeof (short ));
1010- }
1011-
1012- if (internal_data -> internal_buffer_remaining < (frames_to_do * frame_size / sizeof (short ))) {
1013- frames_to_do = internal_data -> internal_buffer_remaining * sizeof (short ) / frame_size ;
1014- }
1015-
1016- if (frames_to_do == 0 ) {
1017- return 0 ;
1018- }
10191006
1020- OSWRAPPER_AUDIO_MEMCPY (buffer , internal_data -> internal_buffer + internal_data -> internal_buffer_pos , frames_to_do * frame_size );
1021- internal_data -> internal_buffer_pos += (frames_to_do * frame_size / sizeof (short ));
1022- internal_data -> internal_buffer_remaining -= (frames_to_do * frame_size / sizeof (short ));
1023- return frames_to_do ;
1007+ return frames_done * sizeof (short ) / frame_size ;
10241008}
10251009/* End Win32 MF implementation */
10261010#else
0 commit comments