Submit
Browse
Anonymous
Login
RSS
SuperCollider Code
Fork Code: SpeechRender / SpeechBuffer
name
code content
/* Little class to render terminal voices into a temp folder (or a given path) Also can be loaded as buffer. Subclass SpeechBuffer calls the render and loads the buffer automatically. May be adaptable to work on linux (if I knew the command used on linux for rendering from speech synthesis) // USAGE: b = SpeechBuffer("I am Super... Collider", 3); // string, voice b.play; play{ PlayBuf.ar(1, b, BufRateScale.kr(b) * 0.5, loop:1)!2 } // WARNING! // do this regularily until I find a better way to deal with the temp files SpeechBuffer.cleanUp // WARNING! // Files have a 22050Hz sample rate! */ SpeechRender { classvar <>voices, <>defaultVoice; classvar <>tempDir, <>tempPrefix; var <cmd, <filePath; *initClass { voices = (); voices.all = [ // 0..4 'Agnes', 'Kathy', 'Princess', 'Vicki', 'Victoria', // 5..9 'Bruce', 'Fred', 'Junior', 'Ralph', 'Alex', // 10..15 'Albert', 'Bad News', 'Bahh', 'Bells', 'Boing', 'Bubbles', // 16..20 'Cellos', 'Deranged', 'Good News', 'Hysterical', 'Pipe Organ', // 21..23 'Trinoids', 'Whisper', 'Zarvox' ]; voices.male = ['Bruce', 'Fred', 'Junior', 'Ralph', 'Alex']; voices.female = ['Agnes', 'Kathy', 'Princess', 'Vicki', 'Victoria']; voices.others = [ 'Albert', 'Bad News', 'Bahh', 'Bells', 'Boing', 'Bubbles', 'Cellos', 'Deranged', 'Good News', 'Hysterical', 'Pipe Organ', 'Trinoids', 'Whisper', 'Zarvox' ]; defaultVoice = voices.male[0]; tempPrefix = "temp_speech_"; tempDir = thisProcess.platform.recordingsDir +/+ "SpeechRenderings"; File.exists(tempDir).not.if { ("mkdir -p " + tempDir.escapeChar($ )).systemCmd; }; } *new { |string, voice, path, opt| ^super.new.init(string, voice, path, opt) } *cleanUp { ("rm" + (tempDir.escapeChar($ )) +/+ tempPrefix ++ "*").systemCmd; "Removed all temporary buffers from %\n".postf(tempDir); } init { |string, voice, path, opt| // start the command cmd = "say"; // add the voice - sybols and strings pass through (voice.isNil).if { voice = defaultVoice }; (voice.class == Integer).if { voice = voices.all[voice] }; cmd = cmd + "-v" + voice.asString; // add more options opt.isNil.if { opt = "" }; cmd = cmd + opt; // add output file path path.isNil.if { filePath = tempDir +/+ tempPrefix ++ Date.localtime.stamp ++ ".aiff" } { filePath = path }; // cmd is ready!!! cmd = cmd + "-o" + (filePath.escapeChar($ )) + string; cmd.systemCmd; // works ok? sync for buffer? ^this } asBuffer { |server| server.isNil.if { server = Server.default }; ^Buffer.read(server, filePath) } } SpeechBuffer : SpeechRender { *new { |string, voice, path, opt, server| ^super.new(string, voice, path, opt).asBuffer(server) } }
code description
Little class I made two years ago to generate buffers out of the speech synthesis engine in Mac OS X. If there is something similar from the command line in Linux or windows, should be easy to adapt the command for those platforms. One of the first things one learn as SC beginner is "bla bla".speak and it is a lot of fun. But one of the most common problems is: one wants to use that command in SynthDefs. If you like the speech synthesizer now you can turn it into a buffer and use it as you wish. Usage: b = SpeechBuffer("I am Super... Collider", 3); // string, voice b.play; play{ PlayBuf.ar(1, b, BufRateScale.kr(b) * 0.5, loop:1)!2 } And you have to clean up your rendering directory with: SpeechBuffer.cleanUp // or: SpeechRender.cleanUp If maybe someone want, this could be turned into a Quark (?) Have fun!
use markdown for formating
category tags
comma separated, i.g. "wild, siren" (do not enter default SC class names, please)
ancestor(s)
comma separated identificators, i.g. "1-C,1-1,1-4M,1-x"
Private?
the code will be accessible by direct url and not visible in public activity
signup to submit public code without captcha
comment of change