How to save manipulated WAV files in object list? - audio

I have the following problem: I want to low-pass filter 240 WAV files. The script is running only till the low-pass filtered sounds are created and shown in the object list ("..._band"). However, Praat does not export them as WAV files. After choosing the output folder, I get the warning message "Command 'Get number of strings' not available for current selection".
In short, my question is how can I save the WAV sounds in the object list individually with their new file names? See also Screenshot.
Script see below.
Thank you very much for your help!
Greetings,
#determine praat version
ver1$ = left$(praatVersion$, (rindex(praatVersion$, ".")-1));
ver1 = 'ver1$'
if ver1 < 5.2
exit Please download a more recent version of Praat
endif
if ver1 == 5.2
ver2$ = right$(praatVersion$, length(praatVersion$) - (rindex(praatVersion$, ".")));
ver2 = 'ver2$'
if ver2 < 4
exit Please download a more recent version of Praat (minor)
endif
endif
beginPause ("Low-Pass Filter Instructions")
comment ("1. Select a folder containing the wave files to be low-pass filtered")
comment ("2. Wave files will be low-pass filtered (0 - 400 Hz)")
comment ("3. Select an output folder for the low-pass filtered wave files to be saved to")
comment ("Click 'Next' to begin")
clicked = endPause("Next", 1);
#wavefile folder path
sourceDir$ = chooseDirectory$ ("Select folder containing wave files")
if sourceDir$ == ""
exit Script exited. You did not select a folder.
else
sourceDir$ = sourceDir$ + "/";
endif
Create Strings as file list... list 'sourceDir$'/*.wav
numberOfFiles = Get number of strings
levels$ = ""
for ifile to numberOfFiles
select Strings list
currentList = selected ("Strings")
filename$ = Get string... ifile
Read from file... 'sourceDir$'/'filename$'
currentSound = selected ("Sound")
filterFreqRange = Filter (pass Hann band)... 0 400 20
select currentSound
Remove
endfor
select currentList
Remove
#output folder path - where the wave files get saved
outputDir$ = chooseDirectory$ ("Select folder to save wave files")
if outputDir$ == ""
exit Script exited. You did not select a folder.
else
outputDir$ = outputDir$ + "/";
endif
numberOfFiles = Get number of strings
for ifile to numberOfFiles
select Strings list
currentList = selected ("Strings")
filename$ = Get string... ifile
currentSound = selected ("Sound")
endif
Save as WAV file... 'outputDir$'/'filename$'
select currentSound
Remove
endfor
#clean up
select currentList
Remove
#clear the info window
clearinfo
#print success message
printline Successfully low-pass filtered 'numberOfFiles' wave files.

At a glance, the command is not available because when you get to that point in the script the selection is empty. It is empty because at the end of the first loop, you select your Strings object and then Remove it.
More generally, your script is not handling the object selection properly, which is a big problem in Praat because available commands change depending on the active selection.
So even if you remove the line where you Remove the list, you will bump into a problem the second time you run Get number of strings because by then you have changed the selection. And even if you remove that line (which you don't really need), you'll still bump into a problem when you run selected("Sound") after selecting the Strings object, because by then you won't have any selected Sound objects (you didn't have them before anyway).
A more idiomatic version of your script, which also runs on a single loop where sounds are read, filtered, and removed one by one (which is also more memory efficient) would look like this:
form Low-Pass Filter...
real From_frequency_(Hz) 0
real To_frequency_(Hz) 400
real Smoothing_(Hz) 20
comment Leave paths empty for GUI selectors
sentence Source_dir
sentence Output_dir
endform
if praatVersion < 5204
exitScript: "Please download a more recent version of Praat"
endif
if source_dir$ == ""
source_dir$ = chooseDirectory$("Select folder containing wave files")
if source_dir$ == ""
exit
endif
endif
if output_dir$ == ""
output_dir$ = chooseDirectory$("Select folder to save filtered files")
if output_dir$ == ""
exit
endif
endif
list = Create Strings as file list: "list", source_dir$ + "/*.wav"
numberOfFiles = Get number of strings
levels$ = ""
for i to numberOfFiles
selectObject: list
filename$ = Get string: i
sound = Read from file: source_dir$ + "/" + filename$
filtered = Filter (pass Hann band): from_frequency, to_frequency, smoothing
Save as WAV file: output_dir$ + "/" + selected$("Sound")
removeObject: sound, filtered
endfor
Although you might be interested to know that, if you do not need the automatic file reading and saving (ie, if you are OK with having your script work on objects from the list) your script could be reduced to
Filter (pass Hann band): 0, 400, 20
which works on multiple selected Sound objects.
If you absolutely need the looping (ie, if you'll be working on really large sets of files) you might also be interested in using the vieweach plugin, with was written to try and minimise this sort of boilerplate (full disclaimer: I wrote the plugin). I wrote a longer blog post about it as well.

Related

Add the same page to a pdf multiple times

I found a code that allows me to add several PDF files to another PDF.
Basically what the code do is fill an array with strings (the names of the files you want to gather) and then loop the command insertpage.
Here's the part of the code that allows to gather several PDF's on a single one
For i = 0 To UBound(a)
Set PartDocs(i) = CreateObject("AcroExch.PDDoc")
PartDocs(i).Open mypath & Trim(a(i))
If i Then
ni = PartDocs(i).GetNumPages()
PartDocs(0).InsertPages n - 1, PartDocs(i), 0, ni, True
n = n + ni
PartDocs(i).Close
Set PartDocs(i) = Nothing
Else
n = PartDocs(0).GetNumPages()
End If
Next
It works great if you have several files, but it doesn't work at all if you are trying to add the same file repeatedly. What the code do in this case is only ad once each file you put in the array.
If you fill an array of 5 elements with the same file, the resultant PDF only will have 1 page corresponding to the file in the array. If you fill with 2 (even if you alternate the names in the array) the resultant PDF will only have 2 pages (one for each file)
Is there any way to add multiple times the same file to a PDF?

praat - delete segment

I have several speech files and I need to cut a certain part of the sound file, from 0.21 milliseconds to 0.45 milliseconds. The script below will select the sound segment from 0.21 milliseconds to 0.45 milliseconds and save it. I want to cut the segment from the speech file and then save it without it. I should probably add another line after "Move end of selection to nearest zero crossing" and change the "Write selected sound..." but I am not sure how exactly.
form Files
sentence InputDir ./
endform
createDirectory ("output")
Create Strings as file list... list 'inputDir$'*.wav
numberOfFiles = Get number of strings
for ifile to numberOfFiles
select Strings list
fileName$ = Get string... ifile
Read from file... 'inputDir$''fileName$'
sound_name$ = selected$ ("Sound")
select Sound 'sound_name$'
Edit
editor Sound 'sound_name$'
Select... 0.21 0.45
Move start of selection to nearest zero crossing
Move end of selection to nearest zero crossing
Write selected sound to WAV file... ./output/'fileName$'
endeditor
select all
minus Strings list
Remove
endfor
select all
Remove
I want to cut the segment from the speech file and then save it without it
It's not clear what you want to do with the deleted segment. Do you want to edit it out (as in, shorten the total duration of the sound?) or simply silence it (as in set the samples contained within to zero?).
Either way, you don't need to open the sound editor (the window with the sound wave and the spectrogram). Below I reproduced your script with some alternatives (and updated the syntax).
form Files
sentence Input_dir ./
positive Start 0.21
positive End 0.45
endform
createDirectory("output")
list = Create Strings as file list: "list", input_dir$ + "*.wav"
numberOfFiles = Get number of strings
for ifile to numberOfFiles
selectObject: list
fileName$ = Get string: ifile
sound = Read from file: input_dir$ + fileName$
sound_name$ = selected$("Sound")
# Find zero crossings
start = Get nearest zero crossing: 1, start
end = Get nearest zero crossing: 1, end
sound_end = Get total duration
# Cut the selected part out, shortening the sound
# by extracting the part before and after and concatenating
before = Extract part: 0, start, "rectangular", 1, "no"
selectObject: sound
after = Extract part: end, sound_end, "rectangular", 1, "no"
selectObject: before, after
new = Concatenate
removeObject: before, after
## Or, if you want to set the selected part to zero
## (since we already have the zero crossings)
# new = Set part to zero: start, end, "at exactly these times"
## Or, if what you want is to get only the selected part
## and not the original sound
# new = Extract part: start, end, "rectangular", 1, "no"
# Either way, the new, modified sound is selected
# and its ID is stored in `new`
Save as WAV file: "./output/" + fileName$
# I prefer a less shotgunny way to remove unwanted objects
removeObject: sound, new
endfor
removeObject: list

Importing multiple excel sheets with multiple tabs into matlab

Hello and good day to all,
I am trying to import some excel sheets having multiple tabs into the matlab. For this I have written small loop but after many tries and adjustments still cant get all the data into matlab. In the source directory I have 15 excel sheets with 8 tabs each containing data in the 52 x 102 cells. The data is in signed form meaning containing positive and negative values. Here below is the code I was working on and I applied different changes which I found on the internet but no success.
srcdir = 'path to the folder';
srcfiles = dir(fullfile(srcdir, '*.xls'));
for i = 1:length(srcfiles)
[status,sheets] = xlsfinfo(srcfiles(i));
for s = 1:numel(sheets)
[data,titles]=xlsread(srcfiles(i).name,sheets{s});
end
end
Right now I am getting this error " Filename must be a string". I even tried to change it to the char to string but still didn't work.
Only once it worked When I instead of giving the path in the source directory i.e srcdir, gave the name of the file directly in xlsread().
Can anybody help where am I doing mistakes?. Thank you
You likely need to specify the full path to the file using fullfile. Also, in the outer for loop you'll need to use srcfiles(i).name instead of srcfiles(i)
srcdir = 'path to the folder';
srcfiles = dir(fullfile(srcdir, '*.xls'));
for k = 1:numel(srcfiles)
filename = fullfile(srcdir, srcfiles(k).name);
[status,sheets] = xlsfinfo(filename);
for s = 1:numel(sheets)
[data,titles] = xlsread(filename, sheets{s});
end
end

Trying to scrub a file with AutoIt

I work with a piece of software that outputs a sql script during upgrades. I am trying to make a tool that will read the file and append " ON IndexDataFile" to the lines that contain "CREATE INDEX" or "CREATE UNIQUE INDEX"
I open that file and write each line to a new file using FileOpen and FileReadLine. Despite a good deal of searching via Google and specific forums I have not been able to figure out how to search each line and append to it when one of the two values are found.
Here is the loop I am using to write to the new file:
While 1
$line_read = FileReadLine($handle_read)
If #error Then ExitLoop
;Code to evaluate line and append text when true
FileWriteLine($handle_write, $line_read)
WEnd
Can someone give me a hint on how to test the string and append when needed or is there a better approach to this?
In one line it would be as easy as:
$line_read = StringRegExpReplace($line_read, "(CREATE\ (?:UNIQUE\ )?INDEX)", "\1 ON IndexData")
You can test your RegEx on regex101.com to make sure, it works as expected.
Or you can write your expression differently if you prefer it fo a better way of reading with an "or" symbol |:
$line_read = StringRegExpReplace($line_read, "(CREATE\ INDEX|CREATE\ UNIQUE\ INDEX)", "\1 ON IndexData")
I was able to resolve it with the following:
While 1
$line_read = FileReadLine($handle_read)
If #error Then ExitLoop
If StringRegExp ( $line_read, "CREATE INDEX") Then $line_read = $line_read & " ON IndexData"
If StringRegExp ( $line_read, "CREATE UNIQUE INDEX") Then $line_read = $line_read & " ON IndexData"
FileWriteLine($handle_write, $line_read)
WEnd

Applescript file search using data from a spreadsheet

I am currently using this Applescript I found that searches for a file name and returns the file path in a text doc. This works fine for finding 1 or 2 files, but I would like to find 500 files that are spread over hundreds of folders. My ideal script would use data from an excel spreadsheet or csv, perform a search, find the file and make a copy of it in a designated folder on my desktop. Any help is appreciated.
Here is the script I found:
tell application "System Events"
activate
set thePattern to text returned of (display dialog "Search for" default answer "")
end tell
if thePattern = "" then return
try
set foundFiles to do shell script "mdfind -name " & quoted form of thePattern & " | /usr/bin/egrep -i " & quoted form of thePattern & "[^/]*/?$ | /usr/bin/grep -vi " & quoted form of thePattern & ".*" & quoted form of thePattern
on error
set foundFiles to "Nothing Returned"
end try
if foundFiles = "" then set foundFiles to "Nothing Returned"
tell application "TextEdit"
activate
delay 0.5
try
set theDoc to document 1
get text of theDoc
if result is not "" then
make new document
set theDoc to result
end if
on error
make new document
set theDoc to result
end try
set text of theDoc to foundFiles
end tell
You need to read the data from the text file, then turn it into a return or linefeed delimited list and do a repeat over the items of this list. Then turn each item (which is actually a line) into e.g. a tab delimited list and again do a (nested) repeat loop over the items of this list. If you know that e.g. item 3 is the file path, you can set a variable to item 3 of the line as text and use this variable in your shell script.
I think you need to show that you understand the concept of repeat loops by posting your own attempt of implementing this. If you do, I'll be happy to come back and help you with the next step.
Kind regards,
Mark

Resources