How to save text-to-speech as a wav with Microsoft SAPI? - c#

I need to turn a text into speech and then save it as wav file.

The following C# code uses the System.Speech namespace in the .Net framework.
It is necessary to reference the namespace before using it, because it is not automatically referenced by Visual Studio.
SpeechSynthesizer ss = new SpeechSynthesizer();
ss.Volume = 100;
ss.SelectVoiceByHints(VoiceGender.Female, VoiceAge.Adult);
ss.SetOutputToWaveFile(#"C:\MyAudioFile.wav");
ss.Speak("Hello World");
I hope this is relevant and helpful.

This is from a few moments' play, so caveat emptor. Worked well for me. I did notice that SpFileStream (which doesn't implement IDisposable, thus the try/finally) prefers absolute paths to relative. C#.
SpFileStream fs = null;
try
{
SpVoice voice = new SpVoice();
fs = new SpFileStream();
fs.Open(#"c:\hello.wav", SpeechStreamFileMode.SSFMCreateForWrite, false);
voice.AudioOutputStream = fs;
voice.Speak("Hello world.", SpeechVoiceSpeakFlags.SVSFDefault);
}
finally
{
if (fs != null)
{
fs.Close();
}
}

And as I've found for how to change output format, we code something like this :
SpeechAudioFormatInfo info = new SpeechAudioFormatInfo(6, AudioBitsPerSample.Sixteen, AudioChannel.Mono);
//Same code comes here
ss.SetOutputToWaveFile(#"C:\MyAudioFile.wav",info);
That's pretty easy and comprehensible.
Cool .net

Related

Check if ISO has Joliet extension by DiscUtils

I'm developing a function to verify if the ISO has Joliet extension.
I use DiscUtils to create the ISO file as follow
CDBuilder builder = new CDBuilder();
builder.UseJoliet = true;
builder.VolumeIdentifier = "A_SAMPLE_DISK";
builder.AddFile("x/x.png", #"C:\Users\Circle\Pictures\Image 1.png");
builder.Build(#"C:\temp\sample.iso");
However, when I read the ISO file. It doesn't be recognized as Joliet
using (FileStream isoStream = File.Open(#"C:\temp\sample.iso", FileMode.Open))
{
CDReader cd = new CDReader(isoStream, true);
if (cd.ActiveVariant == Iso9660Variant.Joliet)
{
// Never enter here
}
}
Not sure which part I did wrong. Any suggestions?
You don't appear to be doing it wrong; however the code won't ever set that ActiveVariant.
If you look at the underlying code, it seems to switch the ActiveVariant to Iso9660Variant.Iso9660 for joliet extensions for the purposes of that field. I don't know the reason for that - it might be a bug, it might have some other esoteric reason for doing it based on some other code in the project.
I've added a couple of comments to the code, and reproduced it here.
case Iso9660Variant.Joliet:
if (svdPos != 0) // <-- Joliet is always a supplementary table.
{
data.Position = svdPos;
data.Read(buffer, 0, IsoUtilities.SectorSize);
SupplementaryVolumeDescriptor volDesc = new SupplementaryVolumeDescriptor(buffer, 0);
Context = new IsoContext { VolumeDescriptor = volDesc, DataStream = _data };
RootDirectory = new ReaderDirectory(Context,
new ReaderDirEntry(Context, volDesc.RootDirectory));
ActiveVariant = Iso9660Variant.Iso9660; // <-- set active variant to base Iso9660
}
break;

I'm trying to save and load choices and its giving me the same error over and over

I keep getting
The process cannot access the file another process is using it
Can someone tell me what's wrong?
public void SaveCheckedChoices()
{
using(StreamWriter writer = new StreamWriter(dataFile))
{
try
{
// Autorun
writer.WriteLine(sublimeAutorun);
writer.WriteLine(sublimePackagesAutorun);
writer.WriteLine(sharpDevelopAutorun);
writer.WriteLine(eclipseAutorun);
writer.WriteLine(outlookAutorun);
writer.WriteLine(youtubeAutorun);
writer.WriteLine(githubAutorun);
writer.WriteLine(trelloAutorun);
File.SetAttributes(dataFile, FileAttributes.Hidden);
}
finally
{
writer.Close();
}
}
}
public void LoadCheckedChoices()
{
StreamReader sr = new StreamReader(dataFile);
// Autorun
sublime.Checked = Convert.ToBoolean(sr.ReadLine());
sublimePackages.Checked = Convert.ToBoolean(sr.ReadLine());
sharpDevelop.Checked = Convert.ToBoolean(sr.ReadLine());
eclipse.Checked = Convert.ToBoolean(sr.ReadLine());
outlook.Checked = Convert.ToBoolean(sr.ReadLine());
youtube.Checked = Convert.ToBoolean(sr.ReadLine());
github.Checked = Convert.ToBoolean(sr.ReadLine());
trello.Checked = Convert.ToBoolean(sr.ReadLine());
sr.Close();
}
I made sure the file was created and that the only thing that was running was SharpDevelop and it still gives me the error, could someone please tell me what the problem is.
File.SetAttributes(dataFile, FileAttributes.Hidden);
Must be moved to after the writer.Close();. I believe it needs exclusive access to the file.
Also you can use File.ReadAllLines in the second function.
And the most important part of my answer. Never, ever, ever, ever, I must insist, NEVER hide a configuration file; EVER. It will come back to haunt you.
EDIT:
For proper serialization read xml or json or the documentation of newtonsoft.json

Creating a file (.htm) in C#

I would like to know the best way to create a simple html file using c#.
Is it using something like System.IO.File.Create?
Something like -
using (FileStream fs = new FileStream("test.htm", FileMode.Create))
{
using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8))
{
w.WriteLine("<H1>Hello</H1>");
}
}
I'll say that File.WriteAllText is a stupid-proof way to write a text file for C# >= 3.5.
File.WriteAllText("myfile.htm", #"<html><body>Hello World</body></html>");
I'll even say that File.WriteAllLines is stupid-proof enough to write bigger html without fighting too much with string composition. But the "good" version is only for C# 4.0 (a little worse version is C# >= 2.0)
List<string> lines = new List<string>();
lines.Add("<html>");
lines.Add("<body>");
lines.Add("Hello World");
lines.Add("</body>");
lines.Add("</html>");
File.WriteAllLines("myfile.htm", lines);
// With C# 3.5
File.WriteAllLines("myfile.htm", lines.ToArray());
I would go with File.Create and then open a StreamWriter to that file if you dont have all the data when you create the file.
This is a example from MS that may help you
class Test
{
public static void Main()
{
string path = #"c:\temp\MyTest.txt";
// Create the file.
using (FileStream fs = File.Create(path, 1024))
{
Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
// Open the stream and read it back.
using (StreamReader sr = File.OpenText(path))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
}
Have a look at the HtmlTextWriter class. For an example how to use this class, for example look at http://www.dotnetperls.com/htmltextwriter.
Reading and writing text files and MSDN info. HTML is just a simple text file with *.HTML extension ;)
Simply opening a file for writing (using File.OpenWrite() for example) will create the file if it does not yet exist.
If you have a look at http://msdn.microsoft.com/en-us/library/d62kzs03.aspx you can find an example of creating a file.
But how do you want to create the html file content? If that's just static then you can just write it to a file.. if you have to create the html on the fly you could use an ASPX file with the correct markup and use a Server.Execute to get the HTML as a string.
Yep, System.IO.File.Create(Path) will create your file just fine.
You can also use a filestream and write to it. Seems more handy to write a htm file

How to tell speech recognizer to start recognition?

I am working on a c# application that uses the SAPI COM component.
In the following code snippe, how can I tell the recognizer to start recognition based on the grammar and the wav file? Thanks.
ISpRecognizer sre = new SpInprocRecognizerClass();
ISpRecoContext context = null;
sre.CreateRecoContext(out context);
ISpRecoGrammar grammar = null;
context.CreateGrammar(1, out grammar);
grammar.LoadCmdFromFile(#"c:\grammar", SPLOADOPTIONS.SPLO_STATIC);
grammar.SetGrammarState(SPGRAMMARSTATE.SPGS_ENABLED);
SpFileStreamClass fs = new SpFileStreamClass();
fs.Open(#"c:\1.wav", SpeechStreamFileMode.SSFMOpenForRead, false);
((SpInprocRecognizerClass)sre).AudioInputStream = fs;
You're almost there.
sre.SetRecoState(SPRECOSTATE.SPRST_ACTIVE);
should do the trick.

Which way to save custom types to a file on a mobile device?

I have a list of custom types, they need to be saved/loaded to/from a file on a mobile device (Windows Mobile 6) what method would be the most suited, taking into account the limited resources of the device?
EDIT:
The data file will be around 2-5mb
How much data are we talking about?
I used an old device (HTC-s620, with a TI OMAP 850 200 MHz processor) to save a 2mb XML file using XML Serialization, in a matter of 3-5 seconds. Very simple programming model. Very easy to do. With a newer device I'm sure it would be much faster.
My usage scenario was, one full load, and one full save, per run.
[XmlRoot("notes")]
public class NoteList : List<Note>
{
// Set this to 'default' or 'preserve'.
[XmlAttribute("space", Namespace = "http://www.w3.org/XML/1998/namespace")]
public string space = "preserve";
public static void Save(NoteList noteList, string NotesFilePath)
{
if (noteList == null) return;
XmlSerializer serializer = new XmlSerializer(typeof(NoteList));
string tmpPath = NotesFilePath + ".tmp";
using (System.IO.FileStream fs = new FileStream(tmpPath, FileMode.Create, FileAccess.Write))
{
serializer.Serialize(fs, noteList);
fs.Close();
}
if (File.Exists(tmpPath))
{
if (File.Exists(NotesFilePath))
{
string oldFile = NotesFilePath + ".bak";
if (File.Exists(oldFile)) File.Delete(oldFile);
File.Move(NotesFilePath, oldFile);
}
File.Move(tmpPath, NotesFilePath);
}
}
public static NoteList Load(string NotesFilePath)
{
if (!System.IO.File.Exists(NotesFilePath))
return null;
NoteList noteList = new NoteList();
XmlSerializer serializer = new XmlSerializer(noteList.GetType());
using (FileStream fs = new FileStream(NotesFilePath, FileMode.Open, FileAccess.Read))
{
noteList = (NoteList)serializer.Deserialize(fs);
fs.Close();
}
return noteList;
}
}
Devices capable of running Win Mobile 6, seem to be able to handle themselves quite well using the "crippled" .NET framework.
But if you want something faster then what System.IO provides, I think you're out of luck (?).
With "custom types", I gather you're referring to classes, and by that I suspect some .NET compliant classes? Then I don't see how you're going to squeeze any more juice...at least no more than
this happy camper got.
I'd recommend looking at SqlLite if you want a proper db but without the bloat. SqlLite is also atomic and power resilient. Otherwise saving to a flat file isn't a problem. Just remember that the power can die on you at any point, including half-way through your write.

Categories