ar1st0crat / NWaves

.NET DSP library with a lot of audio processing functions
MIT License
453 stars 71 forks source link

Can't read output of AudioRecorder Xamarin forms #56

Closed MAminnn closed 2 years ago

MAminnn commented 2 years ago

I'm using Audio Recorder to record audio in Xamarin Forms.

but as I asked here I had a problem with playing the output of Audio Recorder with my Xiaomi Device. and when I installed it on a Samsung Device and it works on it. but when I tried to read and edit it with NWaves. I got this error :

System.IO.EndOfStreamException
Unable to read beyond the end of the stream.

How I can make this output readable for Xiaomi devices and also NWaves?

ar1st0crat commented 2 years ago

Can you provide some code? What WAV file are you trying to read? You can copy this file to PC and try opening it with NWaves using demo apps. Also, I assume, you're trying to open (i.e. read, load) the file - not play it or record it: NWaves does not provide such methods, it's a DSP library.

MAminnn commented 2 years ago

it's the second week which I'm trying to just record audio in xamarin which has an RIFF header, actully an audio which Nwaves can work with. I tried Audio Recorder Plugin and Audio Record and Media Recorder . I asked many questions but got no answer.

the easiest way was Audio Recorder Plugin, but the output hasn't RIFF header. the output of Media Recorder was .3gp which I couldn't convert it to .wav. and the output of Media Recorder was .pcm which also couldn't convert to .wav

here is the last code I tried :

#region Properties
    int SAMPLING_RATE_IN_HZ = 44100;
    ChannelIn CHANNEL_CONFIG = ChannelIn.Mono;
    Android.Media.Encoding AUDIO_FORMAT = Android.Media.Encoding.Pcm16bit;
    int BUFFER_SIZE_FACTOR = 2;
    int BUFFER_SIZE;
    bool RecordingInProgress = false;
    private AudioRecord recorder = null;
    #endregion
    public void Record()
    {
        BUFFER_SIZE = AudioRecord.GetMinBufferSize(SAMPLING_RATE_IN_HZ,
        CHANNEL_CONFIG, AUDIO_FORMAT) * BUFFER_SIZE_FACTOR;
        recorder = new AudioRecord(AudioSource.Mic, SAMPLING_RATE_IN_HZ,
            CHANNEL_CONFIG, AUDIO_FORMAT, BUFFER_SIZE);

        recorder.StartRecording();
        RecordingInProgress = true;
        RecordingTask();
    }
    public Task RecordingTask()
    {
        return Task.Run(() =>
        {
            string path = "appdir/demo.pcm";
            MemoryStream buffer = new MemoryStream(BUFFER_SIZE);
            FileOutputStream outStream = new FileOutputStream(path);
            var demo2 = RecordingInProgress;
            while (RecordingInProgress)
            {
                int result = recorder.Read(buffer.GetBuffer(), 0, BUFFER_SIZE);
                if (result < 0)
                {
                    throw new Exception("Reading of audio buffer failed: ");
                }
                   outStream.Write(buffer.GetBuffer(), 0, BUFFER_SIZE);
            }

        });
    }
    public void Stop()
    {
        if (null == recorder)
        {
            return;
        }

        RecordingInProgress = false;

        recorder.Stop();

        recorder.Release();

        recorder = null;
    }

}

this code makes a .pcm file that can't convert to anything with even cloud converters. I also tried this :

NWaves.Audio.WaveFile waveFile = new NWaves.Audio.WaveFile(buffer.GetBuffer());
                waveFile.SaveTo(new FileStream("appdir/demo.wav", FileMode.Create));

insted of outStream.Write(buffer.GetBuffer(), 0, BUFFER_SIZE); at the bottom of while closing block but it says : No RIFF found

there is about 4 or 5 way to record audio. Nwaves can't work with any of them.

the last try I want to do is add RIFF header to the recorded audio buffer(bytes) programmatically or convert .3gp or .pcm to .wav programmatically.

summary: someone helps me to record an audio in xamarin which Nwaves can work with. thanks

-- this is the last question I asked in stackoverflow. I also asked the same question at this link

actually I want to make a voice changer for android. record audio and change it with Nwaves. but the `Nwaves can't work with the recorded audios in android.

ar1st0crat commented 2 years ago

OK, so you just need to read the contents of .pcm file.

WaveFile class represents the WAV container, i.e. the PCM data + WAV header. The latter is necessary for correct interpretation of the data in 'pcm' part. And since you know exactly the audio parameters during recording, just read the array of samples from the pcm file:


// mono mode and Pcm16bit (like in your example):

DiscreteSignal signal;

// sample.pcm is essentially just an array of bytes:
using (var streamIn = new FileStream("sample.pcm", FileMode.Open))
{
    var length = (int)streamIn.Length / 2;     // divide by 2, because each sample is represented with 2 bytes (Pcm16bit)

    signal = new DiscreteSignal(SAMPLING_RATE_IN_HZ, length);    // reserve space in the signal for number of samples: length

    using (var reader = new BinaryReader(streamIn))
    {
        for (var i = 0; i < length; i++)    // just read samples
        {
            signal[i] = reader.ReadInt16() / 32768f;
        }
    }
}

// then you can save it to WAV file, if necessary:

 var waveFile = new WaveFile(signal);

using (var stream = new FileStream("sample.wav", FileMode.Create))
{
    waveFile.SaveTo(stream);
}
MAminnn commented 2 years ago

Thank you Sooooooooo Much ❤