First time here? Check out the FAQ!
x

WriteBuffer not saving out to SampleFile

+1 vote
631 views

I'm writing a folder of single column text files out to samples. Like the Sample Editor in Kyma, I can process text files in a script one at a time (I have a working script for one text file writing out to buffer SampleFile). I'm looking to make this a batch process on a folder of text files. Currently, I can get an array of text files and loop through (debug is working through this loop of text files), but when I create a new SampleFile and stream values into a WriteBuffer (and then ultimately close), I don't see any .aif files in my Finder. Lots of searching to see if placed in another directory, but cannot find. Do I need to specify a folder for batch .aif files to be stored into first? Or perhaps a user error :) (if there's an easier way to copy code here, I've placed into block quote to make it easier to follow). Thanks for any ideas!

| f file fileName lineValArray samplesFile writeBuffer maxVal filenameArray filesInSameFolder |

maxVal := 0. "init maxVal"
fileName := '0.txt'.
file := Preferences

locateFileNamed: fileName

                 ofType: HostDriverInterface textFileType

locateMessage: ' locate the text file named '.

file == nil ifTrue: [^ self abortForKyma].

filesInSameFolder := file fileNamesInSameFolderWithSameExtension.

"for multiple files in one batch process we will need this."

"Collect the filenames into an array."

filenameArray := 1 to: filesInSameFolder size collect: [:i | i].

filenameArray do: [:i | | "no vars here" |

f := (filesInSameFolder at: i)  asFilename textFileStream.

         "read through file line by line"

         "collect maximum for normalization in first iteration"

        [f atEnd] whileFalse: [

        lineValArray := f nextParameters. "index 1 for 0th element"

                 maxVal := maxVal vmax: ((lineValArray at: 1) abs).

         ].

         f reset. "reset pointer to start of the text file"

 

         "Create a SamplesFile and set up its header."

"self debugWithLabel: 'name' value: ((((filesInSameFolder at: i) asFilename)displayTailWithoutFileExtension))."

samplesFile :=  SamplesFile fromNewFilename: ((((filesInSameFolder at: i) asFilename)displayTailWithoutFileExtension)asString&'_batch.aif') asFilename.

 

"working up to this point!"

samplesFile

    format: #aiff;

    isBigEndian: true;

    channels: 1;

    sampleRate: SignalProcessor sampleRate;

    sampleSize: 24;

    sampleFrames: 0;

    writeHeader.

 

        "Get a stream to write samples."

         writeBuffer := samplesFile writeBuffer.

 

        "self debugWithLabel: 'maxVal' value: (maxVal inverse)."

         maxVal := maxVal inverse. "use inverse for multiplication in writing to audio"

 

        "loop through data again, write to audio file and normalize"

        [f atEnd] whileFalse: [

      lineValArray := f nextParameters. 

"self debugWithLabel: 'lineValArray' value: (lineValArray at: 1)."

              writeBuffer writeSample: (lineValArray at: 1) * ( maxVal). "audio is normalized to data's max value (abs so doesn't matter)"

         ].

 

         "Close the stream."

        writeBuffer close.

].

asked Feb 5, 2019 in Capytalk & Smalltalk by jonbellona (Adept) (1,360 points)
Hi Jon, did you check in the Kyma Folder in a folder called Disk Tracks? Since you are not specifying a directory, it may be saved in there. Please let us know. Thanks.
SSC, no files inside Disk Tracks. I should have specified this too in my initial question.

1 Answer

+2 votes
 
Best answer

You could save the .aif files in the same directory as your data files using construct, for example:

1 to: filesInSameFolder size do: [ :i | | f fn |

    fn := (filesInSameFolder at: i) asFilename.
    f := fn textFileStream.

    "read through file line by line"

    "collect maximum for normalization in first iteration"
    [f atEnd] whileFalse: [
        lineValArray := f nextParameters. "index 1 for 0th element"
        maxVal := maxVal vmax: ((lineValArray at: 1) abs).
        ].

    f reset. "reset pointer to start of the text file"

    "Create a SamplesFile and set up its header."
    samplesFile :=
        SamplesFile fromNewFilename:
            (fn directory construct:
                fn displayTailWithoutFileExtension & '_batch.aif'
).

 

 

 

answered Feb 5, 2019 by ssc (Savant) (128,200 points)
selected Feb 5, 2019 by jonbellona
Holy moly! YES!  (A BIG SMILE as I watch the folder in the finder with text files populate with audio files). I did double check against Sample Editor insert from data file and checked row count of text file with sample count in audio file too. Yes!

I love the Sample Editor to insert from data file (students are using for 0th order data sonification project), and I made this to help students with bulk folders of data that we have.  Just published this bulk conversion script on Sound Library
https://kyma.symbolicsound.com/library/convert-single-column-data-text-files-into-mono-audio-files/

Thanks again!
gem of an example
...