juliencegarra / OpenMATB

OpenMATB: A Multi-Attribute Task Battery promoting task customization, software extendability and experiment replicability
Other
43 stars 32 forks source link

Audio splitting doesn't work #6

Closed lacrimabundus closed 3 years ago

lacrimabundus commented 3 years ago

First of all, great work you did there. Unfortunately I can't get any further with one step:

I would like to cut a new voice together. Unfortunately the script doesn't work properly. Several definitions are missing. I add

_folder = '/home/maxstef/Nextcloud/'

but also _audioname is missing. How did you define this? If I set it e.g.

_audioname = 'german'

, the next error message is that _filedict in line 59 is not defined.

Could you please help me?

Regards, Max

benoitvalery commented 3 years ago

@lacrimabundus The communications plugins expects sound samples to be located in the Sounds directory of the OpenMATB folder. First try to move your audio samples in Sounds/german/male (female). Be sure to save your samples consistently, in .wav format (mono, 44100 Hz). Look into the existing folders (e.g., Sounds/french/female) to see all the samples that are needed to automatically generate phrases.

Then, in your scenario file, don't forget to mention your preference via the following commands (change time to suit your need, in general 00:00:00)

00:00:00;communications;voiceidiom;german
00:00:00;communications;voicegender;male      (or female, again)

And see what happens...

benoitvalery commented 3 years ago

Ho my bad: did you talk about the script provided in the documentation to help with automatic sound splitting ? Here is a more complete version of the script. Note that this is not, strictly speaking, an OpenMATB issue, this scripting being proposed just as an example to help, not as a part of the software.

import os,sys
from subprocess import call

target_list = ['radio','frequency','com_1','com_2','nav_1','nav_2','point', '0','1','2','3','4','5',
               '6','7','8','9', 'a','b','c','d','e','f','g','h', 'i','j','k','l','m','n','o','p',
               'q','r','s','t','u','v','w','x','y','z']  # Must match the recording order

file_dict = {'file_name' : {'gender': 'male', 'langage': 'german'}}
preproc_commands = [['highpass', '200'],['lowpass', '1500']]
options = []

# Select a wav file ##
wave_file_list = [this_file for this_file in os.listdir(os.getcwd()) if '.wav' in this_file]
for f,this_file in enumerate(wave_file_list):
    print str(f) + ' : ' + this_file

correctinput = False
while not correctinput:
    select_file = raw_input('Number of file to process : ')

    try:
        select_file = int(select_file)
        correctinput = True
    except:
        print "Input should be an integer"
        correctinput = False

audio_path = wave_file_list[select_file]
audio_name = audio_path.replace('.wav','')

try:
    folder = file_dict[audio_name]['langage'] + os.sep + file_dict[audio_name]['gender']
except:
    audio_name + ' not present in file_dict. Add it and try again'
    sys.exit()

input_name = audio_path
for this_command in preproc_commands:
    options.append(this_command[0])
    output_name = audio_name + '_' + '_'.join(options) + '.wav'
    call(['sox', input_name, output_name] + this_command)
    input_name = output_name

# Splitting audio
options.append('cut')
input_name = output_name
output_name = audio_name + '_' + '_'.join(options) + '.wav'
call(['sox', input_name, output_name, 'silence', '1', '0.01', '0.2%', '1', '0.1', '0.2%', ':',
      'newfile', ':', 'restart'])

# Move all resulting file in a specific folder
current_path = os.path.dirname(os.path.realpath(__file__))
target_path = current_path + os.sep + folder
list_of_files = [files for files in os.listdir(current_path) if options[-1] in files]
if not os.path.exists(current_path + os.sep + folder):
    os.makedirs(current_path + os.sep + folder)
else: # Empty it
    for this_file in os.listdir(target_path):
        os.remove(target_path + os.sep + this_file)
for this_file in list_of_files:
    file_path = current_path + os.sep + this_file
    this_size = os.path.getsize(file_path)
    # Remove files that are too short
    if this_size < 20000:
        os.remove(file_path)
    else:
        os.rename(file_path, target_path + os.sep + this_file)

# Break if not correct number of audio files, and remove them
list_of_files = [files for files in os.listdir(target_path)]
if len(list_of_files) != 43:
    print "Not 43 audio files... Try again"
    for this_file in list_of_files:
        os.remove(target_path + os.sep + this_file)

# Adding brown noise to each audio file
for f,this_file in enumerate(sorted(list_of_files)):
    input_path = target_path + os.sep + this_file
    output_path = target_path + os.sep + target_list[file_dict[audio_name]['order']][f] + '.wav'
    call(['sox', input_path, 'this_noise.wav', 'synth', 'brownnoise', 'vol','0.08'])
    call(['sox','-m','this_noise.wav', input_path, output_path])
    os.remove(input_path)
    os.remove('this_noise.wav')

# Finally create a pure noise file
#    call(['sox', '-n', 'noise.wav', 'synth', '30', 'brownnoise', 'vol','0.015'])

# Alternatively, copy a good noise.wav version into the working directory
call(['cp', 'brownnoise500ms.wav', target_path + os.sep + 'empty.wav'])

Please let me know if you encounter some difficulties. This script is rather old and can be enhanced.

lacrimabundus commented 3 years ago

Thank you very much. The more detailed script helped and with a few more adjustments I was able to cut the audio file with this script and Python 3.8.


import os,sys
from subprocess import call

target_list = ['radio','frequency','com_1','com_2','nav_1','nav_2','point', '0','1','2','3','4','5',
               '6','7','8','9', 'a','b','c','d','e','f','g','h', 'i','j','k','l','m','n','o','p',
               'q','r','s','t','u','v','w','x','y','z']  # Must match the recording order

file_dict = {'file_name' : {'gender': 'male', 'langage': 'german'}}
preproc_commands = [['highpass', '200'],['lowpass', '1500']]
options = []

# Select a wav file ##
wave_file_list = [this_file for this_file in os.listdir(os.getcwd()) if '.wav' in this_file]
for f,this_file in enumerate(wave_file_list):
    print(str(f) + ' : ' + this_file)

correctinput = False
while not correctinput:
    select_file = input('Number of file to process : ')    
    try:
        select_file = int(select_file)
        correctinput = True
    except:
        print("Input should be an integer")
        correctinput = False

audio_path = wave_file_list[select_file]
audio_name = audio_path.replace('.wav','')

try:
    folder = file_dict[audio_name]['langage'] + os.sep + file_dict[audio_name]['gender']
except:  
    sys.exit(audio_name + ' not present in file_dict. Add it and try again')

input_name = audio_path
for this_command in preproc_commands:
    options.append(this_command[0])
    output_name = audio_name + '_' + '_'.join(options) + '.wav'
    call(['sox', input_name, output_name] + this_command)
    input_name = output_name

# Splitting audio
options.append('cut')
input_name = output_name
output_name = audio_name + '_' + '_'.join(options) + '.wav'
call(['sox', input_name, output_name, 'silence', '1', '0.01', '0.2%', '1', '0.1', '0.2%', ':',
      'newfile', ':', 'restart'])

# Move all resulting file in a specific folder
current_path = os.path.realpath('.')
target_path = current_path + os.sep + folder
list_of_files = [files for files in os.listdir(current_path) if options[-1] in files]
if not os.path.exists(current_path + os.sep + folder):
    os.makedirs(current_path + os.sep + folder)
else: # Empty it
    for this_file in os.listdir(target_path):
        os.remove(target_path + os.sep + this_file)
for this_file in list_of_files:
    file_path = current_path + os.sep + this_file
    this_size = os.path.getsize(file_path)
    # Remove files that are too short
    if this_size < 20000:
        os.remove(file_path)
    else:
        os.rename(file_path, target_path + os.sep + this_file)

# Break if not correct number of audio files, and remove them
list_of_files = [files for files in os.listdir(target_path)]
if len(list_of_files) != 43:
    print("Not 43 audio files... Try again")
    for this_file in list_of_files:
        os.remove(target_path + os.sep + this_file)

# Adding brown noise to each audio file
for f,this_file in enumerate(sorted(list_of_files)):
    input_path = target_path + os.sep + this_file
    output_path = target_path + os.sep + target_list[f] + '.wav'
    call(['sox', input_path, 'this_noise.wav', 'synth', 'brownnoise', 'vol','0.08'])
    call(['sox','-m','this_noise.wav', input_path, output_path])
    os.remove(input_path)
    os.remove('this_noise.wav')

# Finally create a pure noise file
#    call(['sox', '-n', 'noise.wav', 'synth', '30', 'brownnoise', 'vol','0.015'])

# Alternatively, copy a good noise.wav version into the working directory
call(['cp', 'brownnoise500ms.wav', target_path + os.sep + 'empty.wav'])

One small note from me: Yes, it's true, it's not part of the OpenMATB software, but in my eyes it completes the open source idea behind your idea. Everything should be reproducible and changeable. So in my eyes it would make sense to include it in the master branch and see it as part of the software. Maybe only I see it that way. Apart from that everything works great!