{
   "code" : "/*\r\n\r\nLittle class to render terminal voices into a temp folder (or a given path)\r\nAlso 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)\r\n\r\n\r\n// USAGE:\r\n\r\nb = SpeechBuffer(\"I am Super... Collider\", 3); // string, voice\r\nb.play;\r\nplay{ PlayBuf.ar(1, b, BufRateScale.kr(b) * 0.5, loop:1)!2 }\r\n\r\n// WARNING!\r\n// do this regularily until I find a better way to deal with the temp files\r\n\r\nSpeechBuffer.cleanUp\r\n\r\n// WARNING!\r\n// Files have a 22050Hz sample rate!\r\n\r\n*/\r\n\r\nSpeechRender {\r\n\t\r\n\tclassvar <>voices, <>defaultVoice;\r\n\tclassvar <>tempDir, <>tempPrefix;\r\n\t\r\n\tvar <cmd, <filePath;\r\n\t\r\n\t*initClass {\r\n\t\tvoices = ();\r\n\t\tvoices.all = [\r\n\t\t\t// 0..4\t\t\t\r\n\t\t\t'Agnes', 'Kathy', 'Princess', 'Vicki', 'Victoria',\r\n\t\t\t// 5..9\t\t\t\r\n\t\t\t'Bruce', 'Fred', 'Junior', 'Ralph', 'Alex',\r\n\t\t\t// 10..15\t\t\t\r\n\t\t\t'Albert', 'Bad News', 'Bahh', 'Bells', 'Boing', 'Bubbles',\r\n\t\t\t// 16..20\t\t\t\r\n\t\t\t'Cellos', 'Deranged', 'Good News', 'Hysterical', 'Pipe Organ',\r\n\t\t\t// 21..23\t\t\t\r\n\t\t\t'Trinoids', 'Whisper', 'Zarvox'\r\n\t\t];\r\n\t\tvoices.male = ['Bruce', 'Fred', 'Junior', 'Ralph', 'Alex'];\r\n\t\tvoices.female = ['Agnes', 'Kathy', 'Princess', 'Vicki', 'Victoria'];\r\n\t\tvoices.others = [\r\n\t\t\t'Albert', 'Bad News', 'Bahh', 'Bells', 'Boing', 'Bubbles',\r\n\t\t\t'Cellos', 'Deranged', 'Good News', 'Hysterical', 'Pipe Organ',\r\n\t\t\t'Trinoids', 'Whisper', 'Zarvox'\r\n\t\t];\r\n\r\n\t\tdefaultVoice = voices.male[0];\r\n\t\ttempPrefix = \"temp_speech_\";\r\n\t\ttempDir = thisProcess.platform.recordingsDir +/+ \"SpeechRenderings\";\r\n\t\tFile.exists(tempDir).not.if {\r\n\t\t\t(\"mkdir -p \" + tempDir.escapeChar($ )).systemCmd;\r\n\t\t};\r\n\r\n\t}\r\n\t\r\n\t*new { |string, voice, path, opt|\r\n\t\t^super.new.init(string, voice, path, opt)\r\n\t}\r\n\t\r\n\t*cleanUp {\r\n\t\t(\"rm\" + (tempDir.escapeChar($ )) +/+ tempPrefix ++ \"*\").systemCmd;\r\n\t\t\"Removed all temporary buffers from %\\n\".postf(tempDir);\r\n\t}\r\n\t\r\n\tinit { |string, voice, path, opt|\r\n\t\t// start the command\r\n\t\tcmd = \"say\";\r\n\r\n\t\t// add the voice - sybols and strings pass through\r\n\t\t(voice.isNil).if { voice = defaultVoice };\r\n\t\t(voice.class == Integer).if { voice = voices.all[voice] };\r\n\r\n\t\tcmd = cmd + \"-v\" + voice.asString;\r\n\t\t\r\n\t\t// add more options\r\n\t\topt.isNil.if { opt = \"\" };\r\n\t\tcmd = cmd + opt;\r\n\r\n\t\t// add output file path\r\n\t\tpath.isNil.if\r\n\t\t\t{ filePath = tempDir +/+ tempPrefix ++ Date.localtime.stamp ++ \".aiff\" }\r\n\t\t\t{ filePath = path };\r\n\t\t\r\n\t\t// cmd is ready!!!\t\t\r\n\t\tcmd = cmd + \"-o\" + (filePath.escapeChar($ )) + string;\r\n\r\n\t\tcmd.systemCmd; // works ok? sync for buffer?\r\n\r\n\t\t^this\r\n\t}\r\n\t\r\n\tasBuffer { |server|\r\n\t\tserver.isNil.if { server = Server.default };\r\n\t\t^Buffer.read(server, filePath)\r\n\t}\r\n}\r\n\r\nSpeechBuffer : SpeechRender {\r\n\t*new { |string, voice, path, opt, server|\r\n\t\t^super.new(string, voice, path, opt).asBuffer(server)\r\n\t}\r\n}",
   "id" : "1-1IM",
   "is_private" : null,
   "labels" : [
      "speech",
      "class",
      "render",
      "buffer"
   ],
   "description" : "Little class I made two years ago to generate buffers out of the speech synthesis engine in Mac OS X.\r\nIf there is something similar from the command line in Linux or windows, should be easy to adapt the command for those platforms.\r\nOne 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.\r\n\r\nUsage:\r\n\r\nb = SpeechBuffer(\"I am Super... Collider\", 3); // string, voice\r\n\r\nb.play;\r\n\r\nplay{ PlayBuf.ar(1, b, BufRateScale.kr(b) * 0.5, loop:1)!2 }\r\n\r\nAnd you have to clean up your rendering directory with:\r\n\r\nSpeechBuffer.cleanUp // or: SpeechRender.cleanUp\r\n\r\nIf maybe someone want, this could be turned into a Quark (?)\r\nHave fun!",
   "ancestor_list" : [],
   "author" : "rukano",
   "name" : "SpeechRender / SpeechBuffer"
}
