@@ -666,6 +666,64 @@ sf_count_t SFVIO_Tell(void *user_data)
666
666
return sfviodata -> position ;
667
667
}
668
668
669
+ static qbool S_ParseCueMark (const byte * chunk , int len , int cue_point_id , int * sample_length )
670
+ {
671
+ int pos = 0 ;
672
+
673
+ * sample_length = 0 ;
674
+ while (pos < len - 8 ) {
675
+ unsigned int size = BuffLittleLong (chunk + pos + 4 );
676
+
677
+ // Looking for ltxt chunk with purpose "mark"
678
+ if (size >= 20 && !strncmp (chunk + pos , "ltxt" , 4 ) && !strncmp (chunk + pos + 16 , "mark" , 4 )) {
679
+ // Might be for a different cue point
680
+ if (cue_point_id == BuffLittleLong (chunk + pos + 8 )) {
681
+ * sample_length = BuffLittleLong (chunk + pos + 12 );
682
+ return true;
683
+ }
684
+ }
685
+
686
+ pos += size ;
687
+ }
688
+
689
+ return false;
690
+ }
691
+
692
+ static qbool S_FindCuePointSampleLength (SNDFILE * sndfile , int cue_point_id , int * sample_length )
693
+ {
694
+ SF_CHUNK_INFO chunk_info ;
695
+ chunk_info .datalen = 0 ;
696
+ strlcpy (chunk_info .id , "LIST" , sizeof (chunk_info .id ));
697
+ chunk_info .id_size = 4 ;
698
+ SF_CHUNK_ITERATOR * iterator = sf_get_chunk_iterator (sndfile , & chunk_info );
699
+ byte chunk_data [1024 ];
700
+
701
+ * sample_length = 0 ;
702
+
703
+ while (iterator != NULL ) {
704
+ if (sf_get_chunk_size (iterator , & chunk_info ) != SF_ERR_NO_ERROR ) {
705
+ break ;
706
+ }
707
+
708
+ if (chunk_info .datalen >= 24 && chunk_info .datalen <= sizeof (chunk_data )) {
709
+ chunk_info .data = chunk_data ;
710
+
711
+ if (sf_get_chunk_data (iterator , & chunk_info ) != SF_ERR_NO_ERROR ) {
712
+ break ;
713
+ }
714
+ else if (chunk_data [0 ] == 'a' && chunk_data [1 ] == 'd' && chunk_data [2 ] == 't' && chunk_data [3 ] == 'l' ) {
715
+ if (S_ParseCueMark (chunk_data + 4 , chunk_info .datalen - 4 , cue_point_id , sample_length )) {
716
+ return true;
717
+ }
718
+ }
719
+ }
720
+
721
+ iterator = sf_next_chunk_iterator (iterator );
722
+ }
723
+
724
+ return false;
725
+ }
726
+
669
727
sfxcache_t * S_LoadSound (sfx_t * s )
670
728
{
671
729
char namebuffer [256 ];
@@ -711,13 +769,23 @@ sfxcache_t *S_LoadSound (sfx_t *s)
711
769
buf = (short * )Q_malloc (sfinfo .frames * sfinfo .channels * sizeof (short ));
712
770
sf_readf_short (sndfile , buf , sfinfo .frames );
713
771
cue_count = 0 ;
714
- sf_command (sndfile , SFC_GET_CUE_COUNT , & cue_count , sizeof (cue_count ));
772
+ sf_command (sndfile , SFC_GET_CUE_COUNT , & cue_count , sizeof (cue_count ));
715
773
loopstart = -1 ;
716
- if (cue_count != 0 )
717
- {
718
- sf_command (sndfile , SFC_GET_CUE , & sfcues , sizeof (sfcues )) ;
719
- loopstart = sfcues .cue_points [0 ].position ;
774
+
775
+ if (cue_count != 0 ) {
776
+ int loop_sample_count ;
777
+
778
+ sf_command (sndfile , SFC_GET_CUE , & sfcues , sizeof (sfcues )) ;
779
+
780
+ if (S_FindCuePointSampleLength (sndfile , sfcues .cue_points [0 ].position , & loop_sample_count )) {
781
+ loopstart = sfcues .cue_points [0 ].sample_offset ;
782
+ if (loopstart + loop_sample_count > sfinfo .frames ) {
783
+ Sys_Error ("Sound %s has a bad loop length" , s -> name );
784
+ }
785
+ sfinfo .frames = loopstart + loop_sample_count ;
786
+ }
720
787
}
788
+
721
789
sf_close (sndfile );
722
790
723
791
if (sfinfo .channels < 1 || sfinfo .channels > 2 ) {
0 commit comments