I am studying C# by myself by reading some books and watching some tutorials. So, i decided to make a small project at the same time, to get more experience and harden my knowledge. I am trying to create a text to speech program in Georgian(my language) but, i couldn't understand how to append different sounds to each other. For example, when my program wants to say "language" it will divide the word to "la" "n" "gu" "a" "ge" so, i have recorded these parts and want to append them and create a word. I looked for classes on MSDN.COM and found SoundPlayer but, i couldn't figure out how to append the sounds of WAV format. i want to add one sound to another and play a new one, for example i have sound that says "aaa" and the other says "bbbb" i want to get a sound that says "aaabbbb".
To divide words i created an arraylist and used this code.
public ArrayList divide(String s) //დაყოფა და arraylist-ში გადანაწილება
{
ArrayList a = new ArrayList();
int i = 0;
while (i < s.Length)
{
if (s[i] == ',' || s[i] == ' ' || s[i] == '.')
{
a.Add(s.Substring(i, i + 1));
i++;
continue;
}
if (consonant(s[i]) && (i + 1) != s.Length && sonant(s[i + 1]))
{
if (isFirstSonant(s, i))
a.Add(s.Substring(i, i + 2) + "_FIRST");
else
a.Add(s.Substring(i, i + 2) + "_SECOND");
i += 2;
continue;
}
if (sonant(s[i]) && ((i + 1) < s.Length && sonant(s[i]) || i == (s.Length - 1)))
{
if (isFirstSonant(s, i))
a.Add(s.Substring(i, i + 1) + "_FIRST");
else
a.Add(s.Substring(i, i + 1) + "_SECOND");
i++;
continue;
}
if (consonant(s[i]) && ((i + 1) < s.Length && consonant(s[i]) || i == (s.Length - 1)))
{
a.Add(s.Substring(i, i + 1) + "_SECOND");
i++;
continue;
}
}
return a;
}
I have made this program on java and want to do the same on C# so this is my code on java.
this is how i appended the sounds after, putting them in arraylist.
public AudioInputStream append(AudioInputStream main, String s) throws UnsupportedAudioFileException, IOException {
return new AudioInputStream(
new SequenceInputStream(main, find(s)),
main.getFormat(),
main.getFrameLength() + find(s).getFrameLength());
}
private String s;
public void Process() {
try {
AudioInputStream main = AudioSystem.getAudioInputStream(new File("C:/Users/Vato/Desktop/Programing/sintezatori/alphabet/blank.wav"));
ArrayList<String> aa = divide(s);
for(int ii=0;ii<aa.size();ii++) {
main=append(main, aa.get(ii));
System.out.println(aa.get(ii));
}
AudioSystem.write(main, AudioFileFormat.Type.WAVE, new File("C:/Users/Vato/Desktop/Programing/sintezatori/alphabet/result.wav"));
result=main;
AudioInputStream result1 = AudioSystem.getAudioInputStream(new File("C:/Users/Vato/Desktop/Programing/sintezatori/alphabet/result.wav"));
DataLine.Info info =
new DataLine.Info(Clip.class,
result1.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(result1);
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
}
private AudioInputStream result;
public AudioInputStream getResult() {
return result;
}
Which method or class should i use from these http://msdn.microsoft.com/en-us/library/system.media.soundplayer.aspx ?
How can i do the same in C#?
If you don't want to use an existing SDK you could do something like the following:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Media;
using System.Text;
namespace ConsoleApplication3
{
public class SpeechClass
{
private Dictionary<char, string> _letterToFileMapping = new Dictionary<char, string>();
private string _basePath = "\\soundfiles";
public SpeechClass()
{
PopulateMappings();
}
private void PopulateMappings()
{
_letterToFileMapping.Add('a', "asound.wav");
_letterToFileMapping.Add('b', "bsound.wav");
_letterToFileMapping.Add('c', "csound.wav");
_letterToFileMapping.Add('d', "dsound.wav");
}
private void SayWord(string word)
{
var chars = word.ToCharArray();
List<string> filestosay = new List<string>();
foreach (var c in chars)
{
string sound;
if(_letterToFileMapping.TryGetValue(c, out sound))
{
filestosay.Add(sound);
}
}
foreach (string s in filestosay)
{
SoundPlayer p = new SoundPlayer();
p.SoundLocation = Path.Combine(_basePath, s);
p.Play();
}
}
}
}
The AT&T Text-To-Speech SDK is remarkable. You can do custom dictionaries and sounds. http://www.wizzardsoftware.com/text-to-speech-tts.php
Sound player should work:
using System.Media;
InitializeComponent();
Soundplayer MySounds = new SoundPlayer(#"C:\example.wav);
MySounds.Play();
Related
I'm creating a small program which can save and load char array values. Then, I got stuck with two problems.
I have no idea how to make the program end after saving the data.
After loading the char array, it looks the game starts where I saved last time. However, when I put "#" on the place where is already marked, it is accepted. (It is supposed to display error message)
This is when I start new game.
It displays error message properly.
Here is class which includes streamWriter and streamReader.
public class History
{
public char QUIT = 'Y';
public char CONTINUE = 'N';
public char inputGameContinue;
public void WriteFile(char []arr)
{
FileStream sb = new FileStream("MyFile.txt", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(sb);
WriteLine("If you want to save the data, enter" + QUIT +"| To continue, enter "+CONTINUE );
inputGameContinue = char.Parse(ReadLine());
if(inputGameContinue=='Y')
{
sw.Write(arr);
WriteLine("The data is saved!");
}
sw.Close();
}
public void ReadFile()
{
string path = "MyFile.txt";
WriteLine("New game? >> 1 | Load saved data? >>2 ");
int command = int.Parse(ReadLine());
if (command == 2)
{
using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
WriteLine(sr.ReadLine());
}
}
}
}
}
Class2
using System;
using static System.Console;
using System.IO;
namespace createSample
{
public class writeRead
{
public static void Main(string[] args)
{
InputClass inputClass = new InputClass();
ArrayValue arrayValue = new ArrayValue();
History history = new History();
WriteLine("Welcome to game!");
WriteLine("");
history.ReadFile();
do
{
inputClass.inputNumber();
while (true)
{
if (arrayValue.arr[inputClass.input] == '#')
{
WriteLine("{0} already marked '#'. Try another.", inputClass.input);
inputClass.inputNumber();
}
else
{
arrayValue.arr[inputClass.input] = '#';
arrayValue.printArray();
history.WriteFile(arrayValue.arr);
break;
}
}
}
while (checkWhenFinish(arrayValue)!=1 );
WriteLine("All letters are marked with '#'");
Read();
}
public static int checkWhenFinish(ArrayValue a)
{
if(a.arr[0] != '0' && a.arr[1] != '1' && a.arr[2] != '2' && a.arr[3] != '3' && a.arr[4] != '4')
{
return 1;
}
else
{
return 0;
}
}
}
}
Class3
using System;
using System;
using System.Numerics;
using System.Reflection.Emit;
using static System.Console;
using System.IO;
namespace createSample
{
public class ArrayValue
{
public char []arr = { '0','1', '2', '3', '4' };
public void printArray()
{
WriteLine("{0},{1},{2},{3},{4}", arr[0], arr[1], arr[2], arr[3], arr[4]);
}
}
}
Class 4
using System;
using System;
using System.Numerics;
using System.Reflection.Emit;
using static System.Console;
using System.IO;
namespace createSample
{
public class InputClass
{
public int input;
public void inputNumber()
{
while (true)
{
Write("Enter number ? (0 to 4) >> ");
if (!int.TryParse(ReadLine(), out input))
{
input = -1;
}
if (input == 0|| input == 1 || input == 2 || input == 3 || input == 4 )
{
break;
}
else
{
WriteLine("Error! Try again!");
}
}
}
}
}
The problem is when you call history.ReadFile() it can read the file and display its contents, but it never updates arrayValue.arr so when the check is done later, arrayValue.arr[inputClass.input] is still 2.
You might want to pass in arrayValue by reference to ReadFile() to have it updated:
history.ReadFile(ref arrayValue);
then in History
public void ReadFile(ref ArrayValue arrayValue)
{
...
while (sr.Peek() >= 0)
{
var line = sr.ReadLine();
WriteLine(line);
for (int i = 0; i < arrayValue.arr.Length; i++)
{
arrayValue.arr[i] = line[i];
}
}
...
}
Need to find the count of each consecutive characters in a row.
Ex: aaaabbccaa
output: 4a2b2c2a
Character may repeat but need to count only consecutive ones. I also need to maintain original sequence.
I tried following but it groups all characters so was not useful.
str.GroupBy(c => c).Select(g => new { g.Key, Count = g.Count() }).ToList().ForEach(x => str+= x.Count + "" + x.Key)
Regular expression to the rescue ?
var myString = "aaaabbccaa";
var pattern = #"(\w)\1*";
var regExp = new Regex(pattern);
var matches = regExp.Matches(myString);
var tab = matches.Select(x => String.Format("{0}{1}", x.Value.First(), x.Value.Length));
var result = String.Join("", tab);
Here is a LINQ solution:
var input = "aaaabbccaa";
var result = string.IsNullOrEmpty(input) ? "" : string.Join("",input.Skip(1)
.Aggregate((t:input[0].ToString(),o:Enumerable.Empty<string>()),
(a,c)=>a.t[0]==c ? (a.t+c,a.o) : (c.ToString(),a.o.Append(a.t)),
a=>a.o.Append(a.t).Select(p => $"{p.Length}{p[0]}")));
Here is the iterator solution:
var result = RleString("aaaabbccaa");
private static IEnumerable<(char chr, int count)> Rle(string s)
{
if (string.IsNullOrEmpty(s)) yield break;
var lastchar = s.First(); // or s[0]
var count = 1;
foreach (char letter in s.Skip(1))
{
if (letter != lastchar)
{
yield return (lastchar, count);
lastchar = letter;
count = 0;
}
count++;
}
if (count > 0)
yield return (lastchar, count);
}
private static string RleString(string s)
{
return String.Join("",Rle(s).Select(z=>$"{z.count}{z.chr}"));
}
Non-LINQ solution (dotnetfiddle):
using System;
using System.Text;
public class Program
{
public static void Main()
{
// produces 4a2b2c2a
Console.WriteLine(GetConsecutiveGroups("aaaabbccaa"));
}
private static string GetConsecutiveGroups(string input)
{
var result = new StringBuilder();
var sb = new StringBuilder();
foreach (var c in input)
{
if (sb.Length == 0 || sb[sb.Length - 1] == c)
{
sb.Append(c);
}
else
{
result.Append($"{sb.Length}{sb[0]}");
sb.Clear();
sb.Append(c);
}
}
if (sb.Length > 0)
{
result.Append($"{sb.Length}{sb[0]}");
}
return result.ToString();
}
}
This small program will do the trick, but it's not a single line nice linq statement. Just my two cents.
using System;
using System.Linq;
using System.Collections.Generic;
public class Simple {
public static void Main() {
var text = "aaaabbccaa"; //output: 4a3b2c2a
var lista = new List<string>();
var previousLetter = text.Substring(1,1);
var item = string.Empty;
foreach (char letter in text)
{
if (previousLetter == letter.ToString()){
item += letter.ToString();
}
else
{
lista.Add(item);
item = letter.ToString();
}
previousLetter = letter.ToString();
}
lista.Add(item);
foreach (var i in lista)
Console.WriteLine(i.Substring(1,1) + i.Select(y => y).ToList().Count().ToString());
}
}
Here is my non-LINQ version that is quite fast compared to LINQ or Regex:
var prevChar = str[0];
var ct = 1;
var s = new StringBuilder();
var len = str.Length;
for (int j2 = 1; j2 < len; ++j2) {
if (str[j2] == prevChar)
++ct;
else {
s.Append(ct);
s.Append(prevChar);
ct = 1;
prevChar = str[j2];
}
}
s.Append(ct);
s.Append(prevChar);
var final = s.ToString();
}
My LINQ version looks like this, but uses a couple of extension methods I already had:
var ans = str.GroupByRuns().Select(s => $"{s.Count()}{s.Key}").Join();
var chars = "aaaabbccaa".ToCharArray();
int counter = 1;
for (var i = 0; i < chars.Count(); i++)
{
if (i + 1 >= chars.Count() || chars[i] != chars[i + 1])
{
Console.Write($"{counter}{chars[i]}");
counter = 1;
}
else
{
counter++;
}
}
You could have a character var and a counter var outside your Linq scope to keep track of the previous character and the current count and then use linq foreach, but I am just as curious as the rest to why you insist on doing this. Even if you do, the Solution may not be as easy to read as an iterative version and readability and maintenance overhead is very import if anyone else is ever going to read it.
I want to display if the Android "ServiceTestCase" Class is being used in any of the Directories.
The Program currently
1) Displays the Sensor Types the File uses
2) Displays the number of Implementations of the "onSensorChanged" Method
3) Displays the other functions that call the "onSensorChange" Implementation.
How do I display Classes?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ABB.SrcML;
using ABB.SrcML.Data;
using NUnit.Framework;
using System.Collections;
namespace CodeAnalysisToolkit
{
[TestFixture]
public class SimpleAnalyticsCalculator_Thesis
{
//------Test Case Class------------------------------------------------------------------------
[TestCase]
public void CalculateSimpleProjectStats()
{
int NumOfApps = 5;
//-----------Current Working Method to Get sub directories -------------------------
// Get list of files in the specific directory.
string[] TopDirectories = Directory.GetDirectories(#"C:\School\Grad School (Comp Sci)\Thesis\Apps\",
"*.*",
SearchOption.TopDirectoryOnly);
// Display all the files.
//for (int i = 0; i <= NumOfApps; i++)
//{
// Console.WriteLine(TopDirectories[i]);
//}
//Print out all Top Sub Directoies for Specified Path
//foreach (string file in TopDirectories)
//{
// Console.WriteLine(file);
//}
//----------End of Print Sub directory Method----------------------------------------
for (int i = 0; i < NumOfApps; i++)
{
var dataProject = new DataProject<CompleteWorkingSet>(TopDirectories[i],
Path.GetFullPath(TopDirectories[i]),
"..//..//..//SrcML");
Console.WriteLine();
Debug.WriteLine("#############################################");
Debug.WriteLine("Parsing " + TopDirectories[i]);
dataProject.UpdateAsync().Wait();
NamespaceDefinition globalNamespace;
Assert.That(dataProject.WorkingSet.TryObtainReadLock(5000, out globalNamespace));
DisplaySensorTypes(globalNamespace);
//DisplayWhetherAppIsUnitTested();
DisplayCallsToOnSensorChanged(globalNamespace);
}
}
//-------Display Sensor Type Class--------------------------------------------------------------
private void DisplaySensorTypes(NamespaceDefinition globalNamespace)
{
var getDefaultSensorCalls = from statement in globalNamespace.GetDescendantsAndSelf()
from expression in statement.GetExpressions()
from call in expression.GetDescendantsAndSelf<MethodCall>()
where call.Name == "getDefaultSensor"
select call;
foreach (var call in getDefaultSensorCalls)
{
if (call.Arguments.Any())
{
var firstArg = call.Arguments.First();
var components = firstArg.Components;
if (components.Count() == 3 &&
components.ElementAt(0).ToString() == "Sensor" &&
components.ElementAt(1).ToString() == ".")
{
Debug.WriteLine("sensor " + components.ElementAt(2).ToString() + " found");
}
}
}
}
private void DisplayWhetherAppIsUnitTested()
{
throw new NotImplementedException();
}
//-------Display Calls to OnSensorChanged Class------------------------------------------------
private void DisplayCallsToOnSensorChanged(NamespaceDefinition globalNamespace)
{
var senChangedMethods = from method in globalNamespace.GetDescendants<MethodDefinition>()
where method.Name == "onSensorChanged"
select method;
if (senChangedMethods.Count() == 0)
{
Debug.WriteLine("This File Does not contain any Sensor Change Mehtods");
}
else
{
Debug.WriteLine("----- ");
Debug.WriteLine("\r\n");
Debug.WriteLine(senChangedMethods.Count() + " Implementations of " + senChangedMethods.First().GetFullName());
Debug.WriteLine("----- ");
int n = senChangedMethods.Count();
for (int i = 0; i < n; i++)
{
var senChangedMethod = senChangedMethods.ElementAt(i);
Debug.WriteLine("Implementations of onSensorChaged # " + (i + 1) + ": " + senChangedMethod.GetFullName());
//"GetCallsToSelf" returns the number of times the number is called
var callsToSenChanged = senChangedMethod.GetCallsToSelf();
for (int j = 0; j < callsToSenChanged.Count(); j++)
{
var callerMethod = callsToSenChanged.ElementAt(j).ParentStatement.GetAncestorsAndSelf<MethodDefinition>();
if (callerMethod.Any())
{
Debug.WriteLine(" Called by --> " + callerMethod.ElementAt(0).GetFullName());
}
}
//Debug.WriteLine("----- ");
}
} //End of Else does not Equal 0 Check
}
//-------Display Test Class--------------------------------------------------------------
}
}
Using C#, I need to parse a CSV string that doesn't come from a file. I've found a great deal of material on parsing CSV files, but virtually nothing on strings. It seems as though this should be simple, yet thus far I can come up only with inefficient methods, such as this:
using Microsoft.VisualBasic.FileIO;
var csvParser = new TextFieldParser(new StringReader(strCsvLine));
csvParser.SetDelimiters(new string[] { "," });
csvParser.HasFieldsEnclosedInQuotes = true;
Are there good ways of making this more efficient and less ugly? I will be processing huge volumes of strings, so I wouldn't want to pay the cost of all the above. Thanks.
Here is a lightly tested parser that handles quotes
List<string> Parse(string line)
{
var columns = new List<string>();
var sb = new StringBuilder();
bool isQuoted = false;
int nQuotes = 0;
foreach(var c in line)
{
if (sb.Length == 0 && !isQuoted && c == '"')
{
isQuoted = true;
continue;
}
if (isQuoted)
{
if (c == '"')
{
nQuotes++;
continue;
}
else
{
if (nQuotes > 0)
{
sb.Append('"', nQuotes / 2);
if (nQuotes % 2 != 0)
{
isQuoted = false;
}
nQuotes = 0;
}
}
}
if (!isQuoted && c == ',')
{
columns.Add(sb.ToString());
sb.Clear();
continue;
}
sb.Append(c);
}
if (nQuotes > 0)
{
sb.Append('"', nQuotes / 2);
}
columns.Add(sb.ToString());
return columns;
}
Just wondering if anyone knows of a class library that can convert Chinese Pinyin to ones with tones, such as nin2 hao3 ma to nín hǎo ma. It would be similar to this answer, but hopefully using the .NET framework.
Here is my porting of #Greg-Hewgill python algorithm to C#. I haven't run into any issues so far.
public static string ConvertNumericalPinYinToAccented(string input)
{
Dictionary<int, string> PinyinToneMark = new Dictionary<int, string>
{
{0, "aoeiuv\u00fc"},
{1, "\u0101\u014d\u0113\u012b\u016b\u01d6\u01d6"},
{2, "\u00e1\u00f3\u00e9\u00ed\u00fa\u01d8\u01d8"},
{3, "\u01ce\u01d2\u011b\u01d0\u01d4\u01da\u01da"},
{4, "\u00e0\u00f2\u00e8\u00ec\u00f9\u01dc\u01dc"}
};
string[] words = input.Split(' ');
string accented = "";
string t = "";
foreach (string pinyin in words)
{
foreach (char c in pinyin)
{
if (c >= 'a' && c <= 'z')
{
t += c;
}
else if (c == ':')
{
if (t[t.Length - 1] == 'u')
{
t = t.Substring(0, t.Length - 2) + "\u00fc";
}
}
else
{
if (c >= '0' && c <= '5')
{
int tone = (int)Char.GetNumericValue(c) % 5;
if (tone != 0)
{
Match match = Regex.Match(t, "[aoeiuv\u00fc]+");
if (!match.Success)
{
t += c;
}
else if (match.Groups[0].Length == 1)
{
t = t.Substring(0, match.Groups[0].Index) +
PinyinToneMark[tone][PinyinToneMark[0].IndexOf(match.Groups[0].Value[0])]
+ t.Substring(match.Groups[0].Index + match.Groups[0].Length);
}
else
{
if (t.Contains("a"))
{
t = t.Replace("a", PinyinToneMark[tone][0].ToString());
}
else if (t.Contains("o"))
{
t = t.Replace("o", PinyinToneMark[tone][1].ToString());
}
else if (t.Contains("e"))
{
t = t.Replace("e", PinyinToneMark[tone][2].ToString());
}
else if (t.Contains("ui"))
{
t = t.Replace("i", PinyinToneMark[tone][3].ToString());
}
else if (t.Contains("iu"))
{
t = t.Replace("u", PinyinToneMark[tone][4].ToString());
}
else
{
t += "!";
}
}
}
}
accented += t;
t = "";
}
}
accented += t + " ";
}
accented = accented.TrimEnd();
return accented;
}
I've used Microsoft Visual Studio International Pack.
This is 1.0 version. and Feature Pack 2.0.
Hope help you!
I think this line
t = t.Substring(0, t.Length - 2) + "\u00fc";
Should be this instead
t = t.Substring(0, t.Length - 1) + "\u00fc";