From 00c13ec06129efd888c12fbf3688d540ebdc54e5 Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Fri, 1 Nov 2013 16:57:07 -0700 Subject: [PATCH] Fixed HighlyComplete silence detection to handle DC offset silence --- .../HighlyComplete/HCDecoder.mm | 2 +- .../HighlyComplete/circular_buffer.h | 69 +++++++++++++++---- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm index ef4ff17d9..57257cf62 100644 --- a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm +++ b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm @@ -1101,7 +1101,7 @@ static int twosf_info(void * context, const char * name, const char * value) if (![self fillBuffer]) return NO; - silence_test_buffer.remove_leading_silence(1); + silence_test_buffer.remove_leading_silence(); return YES; } diff --git a/Plugins/HighlyComplete/HighlyComplete/circular_buffer.h b/Plugins/HighlyComplete/HighlyComplete/circular_buffer.h index 4b8f3887d..d48dbd45b 100644 --- a/Plugins/HighlyComplete/HighlyComplete/circular_buffer.h +++ b/Plugins/HighlyComplete/HighlyComplete/circular_buffer.h @@ -4,7 +4,7 @@ #include #include -long const silence_threshold = 64; +long const silence_threshold = 8; template class circular_buffer @@ -12,8 +12,14 @@ class circular_buffer std::vector buffer; unsigned long readptr, writeptr, used, size; unsigned long silence_count; + T last_written[2]; + T last_read[2]; public: - circular_buffer() : readptr( 0 ), writeptr( 0 ), size( 0 ), used( 0 ), silence_count( 0 ) { } + circular_buffer() : readptr( 0 ), writeptr( 0 ), size( 0 ), used( 0 ), silence_count( 0 ) + { + memset( last_written, 0, sizeof(last_written) ); + memset( last_read, 0, sizeof(last_read) ); + } unsigned long data_available() { return used; } unsigned long free_space() { return size - used; } T* get_write_ptr( unsigned long & count_out ) @@ -27,7 +33,7 @@ public: unsigned long max_count = size - writeptr; if ( max_count > size - used ) max_count = size - used; if ( count > max_count ) return false; - silence_count += count_silent( &buffer[ 0 ] + writeptr, &buffer[ 0 ] + writeptr + count ); + silence_count += count_silent( &buffer[ 0 ] + writeptr, &buffer[ 0 ] + writeptr + count, last_written ); used += count; writeptr = ( writeptr + count ) % size; return true; @@ -43,7 +49,7 @@ public: if ( !delta ) break; if ( dst ) std::copy( buffer.begin() + readptr, buffer.begin() + readptr + delta, dst ); - silence_count -= count_silent( &buffer[ 0 ] + readptr, &buffer[ 0 ] + readptr + delta ); + silence_count -= count_silent( &buffer[ 0 ] + readptr, &buffer[ 0 ] + readptr + delta, last_read ); if ( dst ) dst += delta; done += delta; readptr = ( readptr + delta ) % size; @@ -55,6 +61,8 @@ public: void reset() { readptr = writeptr = used = 0; + memset( last_written, 0, sizeof(last_written) ); + memset( last_read, 0, sizeof(last_read) ); } void resize(unsigned long p_size) { @@ -66,27 +74,47 @@ public: { return silence_count == used; } - void remove_leading_silence( unsigned long mask ) + void remove_leading_silence() { T const* p; T const* begin; T const* end; - mask = ~mask; if ( used ) { - p = ( begin = &buffer[ 0 ] + readptr ) - 1; + long delta[ 2 ]; + p = begin = &buffer[ 0 ] + readptr; end = &buffer[ 0 ] + ( writeptr > readptr ? writeptr : size ); - while ( ++p < end && ( ( unsigned long ) ( *p + silence_threshold ) <= ( unsigned long ) silence_threshold * 2 ) ); - unsigned long skipped = ( p - begin ) & mask; + while ( p < end ) + { + delta[ 0 ] = p[ 0 ] - last_read[ 0 ]; + delta[ 1 ] = p[ 1 ] - last_read[ 1 ]; + if ( ( (unsigned long)( delta[ 0 ] + silence_threshold ) > ( unsigned long ) silence_threshold * 2 ) || + ( ( unsigned long )( delta[ 1 ] + silence_threshold ) > ( unsigned long ) silence_threshold * 2 ) ) + break; + last_read[ 0 ] += (T) delta[ 0 ]; + last_read[ 1 ] += (T) delta[ 1 ]; + p += 2; + } + unsigned long skipped = p - begin; silence_count -= skipped; used -= skipped; readptr = ( readptr + skipped ) % size; if ( readptr == 0 && readptr != writeptr ) { - p = ( begin = &buffer[ 0 ] ) - 1; + p = begin = &buffer[ 0 ]; end = &buffer[ 0 ] + writeptr; - while ( ++p < end && ( ( unsigned long ) ( *p + silence_threshold ) <= ( unsigned long ) silence_threshold * 2 ) ); - skipped = ( p - begin ) & mask; + while ( p < end ) + { + delta[ 0 ] = p[ 0 ] - last_read[ 0 ]; + delta[ 1 ] = p[ 1 ] - last_read[ 1 ]; + if ( ( (unsigned long)( delta[ 0 ] + silence_threshold ) > ( unsigned long ) silence_threshold * 2 ) || + ( ( unsigned long )( delta[ 1 ] + silence_threshold ) > ( unsigned long ) silence_threshold * 2 ) ) + break; + last_read[ 0 ] += (T) delta[ 0 ]; + last_read[ 1 ] += (T) delta[ 1 ]; + p += 2; + } + skipped = p - begin; silence_count -= skipped; used -= skipped; readptr += skipped; @@ -94,11 +122,22 @@ public: } } private: - static unsigned long count_silent(T const* begin, T const* end) + static unsigned long count_silent(T const* begin, T const* end, T * last) { unsigned long count = 0; - T const* p = begin - 1; - while ( ++p < end ) count += ( ( unsigned long ) ( *p + silence_threshold ) <= ( unsigned long ) silence_threshold * 2 ); + T const* p = begin; + long delta[ 2 ]; + while ( p < end ) + { + delta[ 0 ] = p[ 0 ] - last[ 0 ]; + delta[ 1 ] = p[ 1 ] - last[ 1 ]; + if ( ( (unsigned long)( delta[ 0 ] + silence_threshold ) <= ( unsigned long ) silence_threshold * 2 ) || + ( ( unsigned long )( delta[ 1 ] + silence_threshold ) <= ( unsigned long ) silence_threshold * 2 ) ) + count += 2; + last[ 0 ] += (T) delta[ 0 ]; + last[ 1 ] += (T) delta[ 1 ]; + p += 2; + } return count; } };