Bitsian
Bitsian

Reputation: 2258

Not able to copy a stream to a file

I have to create an audio file from a stream generated by the SpeechSynthesizer.

This is the code am using

var stream = await _SpeechSynth.GetSpeakStreamAsync(text, this.Language);
            var reader = new Windows.Storage.Streams.DataReader(stream.GetInputStreamAt(0));
            await reader.LoadAsync((uint)stream.Size);

            byte[] bytes = new byte[stream.Size];
            reader.ReadBytes(bytes);

             var audioFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(_AgendaAudioFilename, CreationCollisionOption.ReplaceExisting);

             using (var outputStream = await audioFile.OpenAsync(FileAccessMode.ReadWrite))
             {

                 Stream os = outputStream.GetOutputStreamAt(0).AsStreamForWrite();
                 await os.WriteAsync(bytes, 0, bytes.Length);
             }

I found out the problem was that at "os.WriteAsync" was not being awaited. When i put a breakpoint at that line and wait for a few secs then the file was being created properly. Shouldnt the await keyword wait till all the bytes are copied into the stream before going to the next line?

I dont mind if anyone can suggest any better way of copying an InMemoryRandomAccessStream to a file?

EDIT:

Mahantesh's answer works like a charm. Thanks a lot. But am facing a new problem.

After the file is created am trying to open it again to play it but am getting this error.

"Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"

This is my code.

if (!cacheHit)
        {
            var stream = await _SpeechSynth.GetSpeakStreamAsync(text, this.Language);

            //write the stream to disk (seems to be buggy when attempting to playback from the result of the speech synth request)
            var audioFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(_AgendaAudioFilename, CreationCollisionOption.ReplaceExisting);

             outputStream = await audioFile.OpenAsync(FileAccessMode.ReadWrite);

             await RandomAccessStream.CopyAsync(stream, outputStream);                 

        }

        //read agenda from disk and play back the audio
        var agendaStorageFile = await ApplicationData.Current.TemporaryFolder.GetFileAsync(_AgendaAudioFilename);
        var agendaStreamFromDisk = await agendaStorageFile.OpenAsync(FileAccessMode.Read);            

        _MediaPlayer.Url = text;
        _MediaPlayer.SetBytestream(agendaStreamFromDisk);
        _MediaPlayer.Play();    

Am getting the error at this line:

var agendaStreamFromDisk = await agendaStorageFile.OpenAsync(FileAccessMode.Read);

Any idea what might be going wrong?

Upvotes: 0

Views: 818

Answers (2)

Shashi
Shashi

Reputation: 2898

I think you can try with

await RandomAccessStream.CopyAsync(inMemoryStream, outputStream);

Solution to new Problem:

if (!cacheHit)
    {
        var stream = await _SpeechSynth.GetSpeakStreamAsync(text, this.Language);

        //write the stream to disk (seems to be buggy when attempting to playback from the result of the speech synth request)
        var audioFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(_AgendaAudioFilename, CreationCollisionOption.ReplaceExisting);

         using(outputStream = await audioFile.OpenAsync(FileAccessMode.ReadWrite)){
         await RandomAccessStream.CopyAsync(stream, outputStream);}

    }

    //read agenda from disk and play back the audio
    var agendaStorageFile = await ApplicationData.Current.TemporaryFolder.GetFileAsync(_AgendaAudioFilename);
   using (var agendaStreamFromDisk = await agendaStorageFile.OpenAsync(FileAccessMode.Read)){

    _MediaPlayer.Url = text;
    _MediaPlayer.SetBytestream(agendaStreamFromDisk);
    _MediaPlayer.Play();  }

Upvotes: 1

JleruOHeP
JleruOHeP

Reputation: 10386

As you are using await keyword for waiting it is better to use syncronous versions of methods, like

using (var outputStream = audioFile.Open(FileAccessMode.ReadWrite))
{
    Stream os = outputStream.GetOutputStreamAt(0).AsStreamForWrite();
    os.Write(bytes, 0, bytes.Length);
}

Upvotes: 0

Related Questions