I need to convert a wave that i created inside my app into a bit array and then back.
I have no clue how to start.
This is my clase where i create the sound file.
private void forecast(string forecast)
{
MemoryStream streamAudio = new MemoryStream();
System.Media.SoundPlayer m_SoundPlayer = new System.Media.SoundPlayer();
SpeechSynthesizer speech = new SpeechSynthesizer();
speech.SetOutputToWaveStream(streamAudio);
speech.Speak(forecast);
streamAudio.Position = 0;
m_SoundPlayer.Stream = streamAudio;
m_SoundPlayer.Play();
// Set the synthesizer output to null to release the stream.
speech.SetOutputToNull();
}
After you've called Speak, the data is in the MemoryStream. You can get that to a byte array and do whatever you like:
speech.Speak(forecast);
byte[] speechBytes = streamAudio.ToArray();
speechBytes contains the data you're looking for.
Related
I'd like to compress a string using SevenZipSharp and have cobbled together a C# console application (I'm new to C#) using the following code, (bits and pieces of which came from similar questions here on SO).
The compress part seems to work (albeit I'm passing in a file instead of a string), output of the compressed string to the console looks like gibberish but I'm stuck on the decompress...
I'm trying to do the same thing as here (I think):
https://stackoverflow.com/a/4305399/3451115
https://stackoverflow.com/a/45861659/3451115
https://stackoverflow.com/a/36331690/3451115
Appreciate any help, ideally the console will display the compressed string followed by the decompressed string.
Thanks :)
using System;
using System.IO;
using SevenZip;
namespace _7ZipWrapper
{
public class Program
{
public static void Main()
{
SevenZipCompressor.SetLibraryPath(#"C:\Temp\7za64.dll");
SevenZipCompressor compressor = new SevenZipCompressor();
compressor.CompressionMethod = CompressionMethod.Ppmd;
compressor.CompressionLevel = SevenZip.CompressionLevel.Ultra;
compressor.ScanOnlyWritable = true;
var compStream = new MemoryStream();
var decompStream = new MemoryStream();
compressor.CompressFiles(compStream, #"C:\Temp\a.txt");
StreamReader readerC = new StreamReader(compStream);
Console.WriteLine(readerC.ReadToEnd());
Console.ReadKey();
// works up to here... below here output to consol is: ""
SevenZipExtractor extractor = new SevenZip.SevenZipExtractor(compStream);
extractor.ExtractFile(0, decompStream);
StreamReader readerD = new StreamReader(decompStream);
Console.WriteLine(readerD.ReadToEnd());
Console.ReadKey();
}
}
}
The result of compression is binary data - it isn't a string. If you try to read it as a string, you'll just see garbage. That's to be expected - you shouldn't be treating it as a string.
The next problem is that you're trying to read from compStream twice, without "rewinding" it first. You're starting from the end of the stream, which means there's no data for it to decompress. If you just add:
compStream.Position = 0;
before you create the extractor, you may well find it works immediately. You may also need to rewind the decompStream before reading from it. So you'd have code like this:
// Rewind to the start of the stream before decompressing
compStream.Position = 0;
SevenZipExtractor extractor = new SevenZip.SevenZipExtractor(compStream);
extractor.ExtractFile(0, decompStream);
// Rewind to the start of the decompressed stream before reading
decompStream.Position = 0;
trying to convert mp3 file to opus ogg file by using
NAudio: https://github.com/naudio/NAudio
Concentus.OggFile https://github.com/lostromb/concentus.oggfile
using (var source = new MemoryStream(mp3File))
using (var mp3Reader = new MyAudioFileReader(source, FileReaderType.Mp3))
using (var memo = new MemoryStream())
{
var bufferFloat = new float[mp3Reader.Length / (mp3Reader.WaveFormat.BitsPerSample / 8)];
var count = mp3Reader.Read(bufferFloat, 0, bufferFloat.Length);
//convert float to short
var buffShort = new short[count];
var scale = (float)(short.MaxValue);
for (int i = 0; i < count; i++)
{
buffShort[i] = (short)(bufferFloat[i] * scale);
}
//encoder
var encoder = OpusEncoder.Create(48000,
mp3Reader.WaveFormat.Channels,
OpusApplication.OPUS_APPLICATION_AUDIO);
encoder.Bitrate = 65536;//64kbps
//tags
var tags = new OpusTags();
tags.Fields[OpusTagName.Title] = "Title";
tags.Fields[OpusTagName.Artist] = "Artist";
//
var oggOut = new OpusOggWriteStream(encoder, memo, tags);
oggOut.WriteSamples(buffShort, 0, buffShort.Length);
oggOut.Finish();
result = memo.ToArray();
}
I don't know the basics, did some GDD and here is result of what I get.
OpusOggWriteStream.WriteSamples()
requires short[] sample as input.
is it okay the way I convert the NAudio float[] sample provider to short[] ?
probably not cuz output file can't be played .
this code doesn't work and I have no idea why :"D
This is probably too little too late but whatever. As far as I can tell your code looks fine, so to debug I would try just a few things:
There is actually a WriteSamples() overload in OggOpusWriteStream that accepts float[]. Try using that first
I would make sure that mp3Reader.Read actually produces as much data as you believe it to be. I wonder if it might only be returning a single frame of decoded data or something like that. Try writing out the data as uncompressed pcm and sanity checking it
I checked to see if there was some bug in Concentus.Oggfile since you only ever WriteSamples() once - I thought maybe it wouldn't finalize the pages properly in that case, but I can't find anything.
This question already has answers here:
How to write NAudio WaveStream to a Memory Stream?
(2 answers)
Closed 7 years ago.
I worked on this answer for my problem.
I want that 2 wave files that get of database with byte array type concatenate together and play then dispose it!
this is my code:
public static void Play()
{
List<byte[]> audio = dal.SelectSound("خدمات", "احیاء");
byte[] sound = new byte[audio[0].Length + audio[1].Length];
Stream outputSound = Concatenate(sound, audio);
try
{
WaveFileReader wavFileReader = new WaveFileReader(outputSound);
var waveOut = new WaveOut(); // or WaveOutEvent()
waveOut.Init(wavFileReader);
waveOut.Play();
}
catch (Exception ex)
{
Logs.ErrorLogEntry(ex);
}
}
public static Stream Concatenate(byte[] outputFile, List<byte[]> sourceFiles)
{
byte[] buffer = new byte[1024];
Stream streamWriter = new MemoryStream(outputFile);
try
{
foreach (byte[] sourceFile in sourceFiles)
{
Stream streamReader = new MemoryStream(sourceFile);
using (WaveFileReader reader = new WaveFileReader(streamReader))
{
int read;
while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
streamWriter.Write(buffer, 0, read);
}
}
}
}
return streamWriter;
}
but I get this error:
Not a WAVE file - no RIFF header
after execute this line:
WaveFileReader wavFileReader = new WaveFileReader(outputSound);
Thanks in advance.
WAV files are not simply an array of bytes, each WAV file has a 44-byte header (the RIFF header) to tell any software how to play it back. Among other things, this header contains information about the length of the file, so in concatenating two WAV files the way you're doing it, you'll end up with two big problems. Firstly, the first WAV file will still have its old header at the start, which will tell your software that the file shorter than it actually is, and secondly, the header of the second WAV file will be stuck in middle of your new file, which will probably sound very strange if you play it back!
So when you're concatenating your files, you'll need to do the following:
Remove the first 44 bytes of each file
Concatenate the two byte
arrays
Create a new header according to the RIFF header specification
Put this header at the
front of your concatenated byte arrays
Call WaveFileReader wavFileReader = new
WaveFileReader(outputSound);
I need a fast method to store all samples of a wav file in an array. I am currently working around this problem by playing the music and storing the values from the Sample Provider, but this is not very elegant.
From the NAudio Demo I have the Audioplayer Class with this Method:
private ISampleProvider CreateInputStream(string fileName)
{
if (fileName.EndsWith(".wav"))
{
fileStream = OpenWavStream(fileName);
}
throw new InvalidOperationException("Unsupported extension");
}
var inputStream = new SampleChannel(fileStream, true);
var sampleStream = new NotifyingSampleProvider(inputStream);
SampleRate = sampleStream.WaveFormat.SampleRate;
sampleStream.Sample += (s, e) => { aggregator.Add(e.Left); }; // at this point the aggregator gets the current sample value, while playing the wav file
return sampleStream;
}
I want to skip this progress of getting the sample values while playing the file, instead I want the values immediatly without waiting till the end of the file. Basically like the wavread command in matlab.
Use AudioFileReader to read the file. This will automatically convert to IEEE float samples. Then repeatedly call the Read method to read a block of samples into a float[] array.
I have a file that is created using
var recordIntent = new Intent(MediaStore.Audio.Media.RecordSoundAction);
I have no problems retrieving the URI of this file. And I can play it back using MediaPlayer without any difficulties.
However, I would like to send this as a response to my webAPI, and am looking at a way to convert the Audio File represented by this URI to a byte array that I can convert to JSON.
With an image file i can do something like
Bitmap bitmap = MediaStore.Images.Media.GetBitmap(ContentResolver, responseUri);
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
byte[] bitmapData = stream.ToArray();
Is there a similar way I can retrieve the Byte Array data from my audio URI?
edit:
formatting of Audio URI.
responseUri = {content://media/external/audio/media/21}
Taken from a ton of different SO answers, and a little bit of extra conversion for mono from Java I came up with these results.
public String GetRealPathFromUri(Uri contentUri){
String[] proj = {MediaStore.Audio.AudioColumns.Data};
ICursor cursor = ManagedQuery(contentUri, proj, null, null, null);
int column_index = cursor.GetColumnIndex(MediaStore.Audio.AudioColumns.Data);
cursor.MoveToFirst();
return cursor.GetString(column_index);
}
var responseRealPath = GetRealPathFromUri(responseUri);
var getBytes = System.IO.File.ReadAllBytes(responseRealPath);
var responseBase = Convert.ToBase64String(getBytes);