@ -33,32 +33,67 @@ struct GunshotClassifier::Impl {
bool LoadLabelMap ( const std : : string & path ) {
std : : ifstream f ( path ) ;
if ( ! f ) return false ;
std : : string line ;
std : : string content ( ( std : : istreambuf_iterator < char > ( f ) ) ,
std : : istreambuf_iterator < char > ( ) ) ;
labels . clear ( ) ;
while ( std : : getline ( f , line ) ) {
// Parse "index: label" format
size_t pos = line . find ( ' : ' ) ;
if ( pos = = std : : string : : npos ) continue ;
int idx = 0 ;
try {
idx = std : : stoi ( line . substr ( 0 , pos ) ) ;
} catch ( . . . ) {
continue ;
}
std : : string label = line . substr ( pos + 1 ) ;
// trim whitespace
size_t start = label . find_first_not_of ( " \t \r \n " ) ;
size_t end = label . find_last_not_of ( " \t \r \n " ) ;
if ( start ! = std : : string : : npos & & end ! = std : : string : : npos ) {
label = label . substr ( start , end - start + 1 ) ;
} else {
label . clear ( ) ;
// Try simple JSON object format: {"0": "ambient", "1": "threat"}
if ( content . find ( ' { ' ) ! = std : : string : : npos ) {
size_t pos = 0 ;
while ( ( pos = content . find ( ' " ' , pos ) ) ! = std : : string : : npos ) {
size_t key_start = pos + 1 ;
size_t key_end = content . find ( ' " ' , key_start ) ;
if ( key_end = = std : : string : : npos ) break ;
std : : string key = content . substr ( key_start , key_end - key_start ) ;
int idx = - 1 ;
try { idx = std : : stoi ( key ) ; } catch ( . . . ) { }
size_t colon = content . find ( ' : ' , key_end ) ;
if ( colon = = std : : string : : npos ) break ;
size_t val_quote = content . find ( ' " ' , colon ) ;
if ( val_quote = = std : : string : : npos ) break ;
size_t val_end = content . find ( ' " ' , val_quote + 1 ) ;
if ( val_end = = std : : string : : npos ) break ;
std : : string label = content . substr ( val_quote + 1 , val_end - val_quote - 1 ) ;
if ( idx > = 0 ) {
if ( idx > = static_cast < int > ( labels . size ( ) ) ) labels . resize ( idx + 1 ) ;
labels [ idx ] = label ;
}
pos = val_end + 1 ;
}
if ( idx > = static_cast < int > ( labels . size ( ) ) ) {
labels . resize ( idx + 1 ) ;
} else {
// Fallback: "index: label" line format
size_t line_start = 0 ;
while ( line_start < content . size ( ) ) {
size_t line_end = content . find ( ' \n ' , line_start ) ;
if ( line_end = = std : : string : : npos ) line_end = content . size ( ) ;
std : : string line = content . substr ( line_start , line_end - line_start ) ;
line_start = line_end + 1 ;
std : : size_t pos = line . find ( ' : ' ) ;
if ( pos = = std : : string : : npos ) continue ;
int idx = 0 ;
try {
idx = std : : stoi ( line . substr ( 0 , pos ) ) ;
} catch ( . . . ) {
continue ;
}
std : : string label = line . substr ( pos + 1 ) ;
std : : size_t start = label . find_first_not_of ( " \t \r \n " ) ;
std : : size_t end = label . find_last_not_of ( " \t \r \n " ) ;
if ( start ! = std : : string : : npos & & end ! = std : : string : : npos ) {
label = label . substr ( start , end - start + 1 ) ;
} else {
label . clear ( ) ;
}
if ( idx > = static_cast < int > ( labels . size ( ) ) ) {
labels . resize ( idx + 1 ) ;
}
labels [ idx ] = label ;
}
labels [ idx ] = label ;
}
// Remove empty entries and compact
std : : vector < std : : string > cleaned ;
for ( const auto & l : labels ) {