MMS-MSG es un marco altamente modular y flexible para la generación de mezclas de habla. Extiende la base de código de la base de datos SMS-WSJ para la generación de señales de mezcla para poder generar mezclas de voz de estilo reuniones y señales de mezcla correspondientes a bases de datos de mezcla de habla clásica.
Los datos de la reunión describen una configuración altamente dinámica. Tanto el entorno con MMS-MSG, no pretendemos proporcionar una nueva base de datos.
En cambio, queremos proporcionar un marco adaptable que permita la creación de prototipos y la evaluación de cumplir con el sistema de transcripción y transcripción en tantos entornos como sea posible.
El aspecto central de MMS-MSG es la generación de datos de estilo de reunión. Las reuniones se generan de manera modular. Los parámetros ajustables son:
El proceso de muestreo está modularizado, por lo que se pueden crear muchos escenarios cambiando ligeramente la tubería de muestreo. Proporcionamos clases de ejemplo para mostrar cómo se utilizan los módulos individuales. Si no es compatible con un escenario, los nuevos módulos de muestreo se pueden implementar fácilmente para adaptar MMS-MSG a sus requisitos.
El proceso de simulación de datos de MMS-MSG se divide en el muestreo de parámetros y la generación de datos real. A través de esto, apoyamos la generación de datos a pedido. De esta manera, solo los datos de origen y los parámetros de la reunión deben guardarse, lo que permite la simulación de varios escenarios de reunión al tiempo que minimiza el espacio de disco requerido. Sin embargo, también apoyamos la generación fuera de línea de datos de reuniones si se requiere para guardarlos en el disco duro para su flujo de trabajo.
Proporcionamos código para generar mezclas de voz de acuerdo con las especificaciones de las bases de datos de separación de fuente utilizadas actualmente, donde las expresiones únicas de múltiples altavoces se superponen parcial o completamente entre sí. Al usar MMS-MSG para generar datos de capacitación para estas bases de datos, ofrecemos un soporte nativo de la mezcla dinámica.
Bases de datos de mezcla de voz compatibles:
Planificado:
El generador de mezcla usa lazy_dataset. Mientras que la funcionalidad central de MMS_MSG se puede usar sin LAZEY_DATASET, algunas características (como la mezcla dinámica y la abstracción de la base de datos) no están disponibles.
from mms_msg . databases . classical . full_overlap import WSJ2Mix
from mms_msg . sampling . utils import collate_fn
db = WSJ2Mix ()
# Get a train dataset with dynamic mixing
# This dataset only emits the metadata of the mixtures, it doesn't load
# the data yet
ds = db . get_dataset ( 'train_si284_rng' )
# The data can be loaded by mapping a database's load_example function
ds = ds . map ( db . load_example )
# Other dataset modifications (see lazy_dataset doc)
ds = ds . shuffle ( reshuffle = True )
ds = ds . batch ( batch_size = 8 ). map ( collate_fn )
# ...
# Parallelize data loading with lazy_dataset
ds = ds . prefetch ( num_workers = 8 , buffer_size = 16 )
# The dataset can now be used in any training loop
for example in ds :
# ... do fancy stuff with the example.
# The loaded audio data is in example['audio_data']
print ( example )
Cualquier otra rutina de modificación de datos se puede asignar a ds
directamente después de cargar el ejemplo.
Un lazy_dataset.Dataset
se puede conectar a una torch.utils.data.DataLoader
:
from mms_msg . databases . classical . full_overlap import WSJ2Mix
db = WSJ2Mix ()
ds = db . get_dataset ( 'train_si284_rng' ). map ( db . load_example )
# Parallelize data loading with torch.utils.data.DataLoader
from torch . utils . data import DataLoader
loader = DataLoader ( ds , batch_size = 8 , shuffle = True , num_workers = 8 )
for example in loader :
print ( example )
Los ejemplos de entrada deben tener esta estructura:
example = {
'audio_path' : {
'observation' : 'single_speaker_recording.wav'
},
'speaker_id' : 'A' ,
'num_samples' : 1234 , # Number of samples of the observation file
# 'num_samples': {'observation': 1234} # Alernative, if other audios are present
'dataset' : 'test' , # The input dataset name
'example_id' : 'asdf1234' , # Unique ID of this example. Optional if the input data is passes as a dict
'scenario' : 'cafe-asdf1234' , # (Optional) If provided, mms_msg makes sure that all examples of the same speaker in a mixture share the same scenario
# ... (any additional keys)
}
Después de seleccionar enunciados para una mezcla, estos ejemplos de enunciado se normalizan y se "recopilan", lo que da como resultado una estructura similar a esta:
example = {
'audio_path' : {
'original_source' : [
'source1.wav' ,
'source2.wav' ,
],
},
'speaker_id' : [
'A' , 'B'
],
'num_samples' : { # The structure under some keys mirrors the structure in 'audio_path'
'original_source' : [
1234 , 4321
]
},
'source_id' : [ # Reference to the source examples this mixture was created from
'asdf1234' , 'asdf1235'
],
...
}
A partir de dicha estructura, los módulos de muestreo se pueden aplicar para llenar el ejemplo con más información, por ejemplo, compensaciones o escala de las expresiones.
Se proporcionan clases o definiciones de bases de datos para algunos escenarios comunes en mms_msg.databases
. Cada clase de base de datos tiene que definir dos métodos:
get_mixture_dataset
, que encapsula la etapa de "muestreo" y construye una tubería de módulos de muestreo, yload_example
, que proporciona la etapa de "simulación", es decir, cargando y mezclando los datos de audio.Una base de datos básica (sin parámetros) se vería así:
from mms_msg . databases . database import MMSMSGDatabase
from lazy_dataset . database import JsonDatabase
import mms_msg
class MyDatabase ( JsonDatabase , MMSMSGDatabase ):
def get_mixture_dataset ( self , name , rng ):
ds = mms_msg . sampling . source_composition . get_composition_dataset (
input_dataset = super (). get_dataset ( name ),
num_speakers = 2 ,
rng = rng ,
)
ds = ds . map ( mms_msg . sampling . pattern . classical . ConstantOffsetSampler ( 8000 ))
ds = ds . map ( mms_msg . sampling . environment . scaling . ConstantScalingSampler ( 0 ))
return ds
def load_example ( self , example ):
return mms_msg . simulation . anechoic . anechoic_scenario_map_fn ( example )
y puede ser instanciado con
db = MyDatabase ( 'path/to/source/database.json' )
La estructura de la tubería de muestreo del conjunto de datos se describe en la siguiente sección.
Este es un ejemplo de una tubería de muestreo simple para un solo conjunto de datos:
import mms_msg
input_ds = ... # Get source utterance examples from somewhere
# Compute a composition of base examples. This makes sure that the speaker distribution
# in the mixtures is equal to the speaker distribution in the original database.
ds = mms_msg . sampling . source_composition . get_composition_dataset ( input_dataset = input_ds , num_speakers = 2 )
# If required: Offset the utterances
ds = ds . map ( mms_msg . sampling . pattern . classical . ConstantOffsetSampler ( 0 ))
# If required: Add log_weights to simulate volume differences
ds = ds . map ( mms_msg . sampling . environment . scaling . UniformScalingSampler ( max_weight = 5 ))
El proceso de muestreo siempre comienza con la creación de una "composición de origen", es decir, expresiones de muestreo (base) para cada mezcla. Esto se hace en get_composition_dataset
, que implementa un algoritmo de muestreo similar a SMS-WSJ que utiliza cada enunciado de la base de datos de origen con la misma frecuencia.
Después de esto, los módulos de muestreo se pueden aplicar para simular diferentes patrones o entornos de habla. El ejemplo anterior establece todas las compensaciones a cero (es decir, todas las expresiones comienzan al comienzo de la mezcla) con el ConstantOffsetSampler
y muestras una escala aleatoria con un máximo de 5dB con UniformScalingSampler
.
Hay muchos otros módulos de muestreo disponibles, incluido uno que simula patrones de habla de estilo de reunión. Se pueden encontrar ejemplos para esto en este cuaderno.
Las mezclas en mms_msg
se crean aplicando módulos de muestreo individuales a un ejemplo uno tras otro. Cada módulo de muestreo es completamente determinista, es decir, su salida solo depende de sus hiperparámetros y el ejemplo de entrada, pero no se le permite mantener un estado mutable. Esto es para garantizar la reproducibilidad: el muestreo no depende del orden en el que se generan las mezclas, el número u orden en el que se aplican los módulos.
Un módulo de muestreo es un llamado que recibe una mezcla (intermedia) como diccionario, la modifica y la devuelve. Un módulo de muestreo básico, implementado como una función sin hiperparámetros, podría verse así:
import mms_msg
def my_sampling_module ( example : dict ) -> dict :
# Get a deterministic random number generator based on the input example
# and an additional seed string. The seed string ensures that the RNGs
# differ between different sampling modules
rng = mms_msg . sampling . utils . rng . get_rng_example ( example , 'my_sampler' )
# Sample whatever based on RNG and possibly the contents of example
example [ 'my_random_number' ] = rng . random ()
return example
Una parte importante es la función mms_msg.sampling.utils.rng.get_rng_example
. Devuelve un objeto np.random.Generator
que se inicializa con una semilla calculada a partir de la información básica del diccionario de ejemplo (Ejemplo-ID y DataSet) y una cadena de semillas adicional. Esto significa que los números aleatorios generados en un módulo son iguales cada vez que el módulo se aplica al mismo ejemplo de entrada.
Si su módulo de muestreo tiene hiperparámetros, recomendamos un DataClass congelado para garantizar la inmutabilidad:
import mms_msg
from dataclasses import dataclass
@ dataclass ( frozen = True )
class MySamplingModule :
size : int = 42
def __call__ ( self , example ):
rng = mms_msg . sampling . utils . rng . get_rng_example ( example , 'my_sampler' )
# Sample whatever based on RNG and possibly the contents of example
example [ 'my_random_number' ] = rng . random ( self . size )
return example
Se da un ejemplo más práctico en este cuaderno.
MMS-MSG se propuso en la siguiente publicación:
@inproceedings { cordlandwehr2022mms_msg ,
title = { MMS-MSG: A Multi-purpose Multi-Speaker Mixture Signal Generator } ,
author = { Tobias Cord-Landwehr and Thilo von Neumann and Christoph Boeddeker and Reinhold Haeb-Umbach } ,
year = { 2022 } ,
booktitle = { International Workshop on Acoustic Signal Enhancement (IWAENC) } ,
publisher = { {IEEE} } ,
} ```