25 May '13 - 05:30 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1] 2  All
  Reply  |  Print  
Author Topic: continue recording and append on existing wav  (Read 1906 times)
Benchjoe
Posts: 13


« on: 19 Mar '12 - 12:29 »
Reply with quoteQuote

Hi!

I'm new to BASS and want to create an application for recording voice.
Recorded should be in wav-files and users should be able to record-pause-continuing
recording. My code works only on the first click on "record", but i'm not able to
continue recording in the same file.
Here it is:
               
Quote
_Recording = true;
                _myRecProc = new RECORDPROC(MyRecording);
                _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero);
               
                if (_enc!=null)//continue
                {
                    _enc.OutputFile = "test.wav";
                    _enc.Start(null, IntPtr.Zero, true);
                    _enc.Force16Bit = true;
                    Bass.BASS_ChannelPlay(_recHandle, false);
                }
                else
                {
                    _enc = new EncoderWAV(_recHandle);
                    _enc.OutputFile = "test.wav";
                    _enc.Start(null, IntPtr.Zero, false);
                    _enc.Force16Bit = true;
                    Bass.BASS_ChannelPlay(_recHandle, true);
                }

I can't see my mistake, am i on the wrong way?
Many greetings,
Joe
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #1 on: 19 Mar '12 - 15:13 »
Reply with quoteQuote

It looks like the problem there is that the WAV writer is left set on the original recording, so it won't receive data from the subsequent recordings. When using BASSenc directly, it is possible to move an encoder to another channel via the BASS_Encode_SetChannel function. When using BASS.Net's encoder classes, I believe that is done via the encoder's ChannelHandle property, something like this...

                if (_enc!=null)//continue
                {
                    _enc.ChannelHandle = _recHandle;
                    Bass.BASS_ChannelPlay(_recHandle, false);
                }
Logged
Benchjoe
Posts: 13


« Reply #2 on: 21 Mar '12 - 10:43 »
Reply with quoteQuote

Hi!


               if (_enc!=null)//continue
                {
                    _enc.ChannelHandle = _recHandle;
                    Bass.BASS_ChannelPlay(_recHandle, false);
                }
Many thanks, it works.

How can i play the recorded wav after pausing?
I want to hear my recording, stop at a position and continue recording from this position.

TIA,
Joe
« Last Edit: 21 Mar '12 - 11:53 by Benchjoe » Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #3 on: 21 Mar '12 - 16:02 »
Reply with quoteQuote

How can i play the recorded wav after pausing?

You can use BASS_StreamCreateFile. Note the WAV file's header won't contain correct length information until it is updated at the end of the file writing (when the encoder is freed), so some apps may refuse to play the file before then, but BASS_StreamCreateFile should be fine with it.

I want to hear my recording, stop at a position and continue recording from this position.

Do you want to continue recording at a different position in the file, not at the end of it? If so, I'm afraid that won't be possible with BASSenc, and you will need to implement the file writing yourself (write the sample data to the file in your RECORDPROC function) so that you have control over the file position. You will need to put a RIFF/WAVE header at the front of the file; examples of doing that can be found in the RECTEST and WRITEWAV examples in the BASS package.
Logged
Benchjoe
Posts: 13


« Reply #4 on: 23 Mar '12 - 11:55 »
Reply with quoteQuote

Hi!

Quote
Do you want to continue recording at a different position in the file, not at the end of it?
Correct!

What about WaveWriter Class in Bass? Is it possible to write in wavefile from a given position?
Next I need a Insert/Overwrite mode...

Thx,
Joe
« Last Edit: 23 Mar '12 - 13:43 by Benchjoe » Logged
Benchjoe
Posts: 13


« Reply #5 on: 9 Aug '12 - 07:36 »
Reply with quoteQuote

Hi!

Quote
You will need to put a RIFF/WAVE header at the front of the file; examples of doing that can be found in the RECTEST and WRITEWAV examples in the BASS package.

Where can i find a description of the wave header like on my screenshot, which i got from wavewriter class? In detail, i need information about the shown WAVEfmt_ chunk.

I want to update this header, but i get a damaged file:
public void WaveHeaderReading(string spath)
        {
            FileStream fs = new FileStream(spath, FileMode.Open, FileAccess.Read);

            BinaryReader br = new BinaryReader(fs);
            length = (int)fs.Length - 8;
            fs.Position = 22;
            channels = br.ReadInt16();
            fs.Position = 24;
            samplerate = br.ReadInt32();
            fs.Position = 34;

            BitsPerSample = br.ReadInt16();
            DataLength = (int)fs.Length - 44;
            br.Close();
            fs.Close();

        }

        public void WaveHeaderWriting(string sPath)
        {
            FileStream fs = new FileStream(sPath, FileMode.Open, FileAccess.Write);

            BinaryWriter bw = new BinaryWriter(fs);
            fs.Position = 0;
            bw.Write(new char[4] { 'R', 'I', 'F', 'F' });

            bw.Write(length);

            bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });

            bw.Write((int)16);

            bw.Write((short)1);
            bw.Write(channels);

            bw.Write(samplerate);//int32 samplerate

            bw.Write((int)(samplerate * ((BitsPerSample * channels) / 8)));//byterate

            bw.Write((short)((BitsPerSample * channels) / 8));//Blockalign

            bw.Write((short)BitsPerSample);//bitspersample
            //extraparamsize 2bytes
            bw.Write((short)1);//
            //extraparams??
            bw.Write(new char[4] { 'd', 'a', 't', 'a' });
            bw.Write(DataLength);
            bw.Close();
            fs.Close();

TIA,
Joe

* waveheader2.jpg (34.26 KB - downloaded 62 times.)
« Last Edit: 9 Aug '12 - 08:37 by Benchjoe » Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #6 on: 9 Aug '12 - 17:59 »
Reply with quoteQuote

You can find details on the WAVE file format here:

   www.sonicspot.com/guide/wavefiles.html
Logged
Benchjoe
Posts: 13


« Reply #7 on: 10 Aug '12 - 10:18 »
Reply with quoteQuote

You can find details on the WAVE file format here:

   www.sonicspot.com/guide/wavefiles.html

Thank you, now i get a correct header!
Logged
Benchjoe
Posts: 13


« Reply #8 on: 10 Aug '12 - 13:18 »
Reply with quoteQuote

Hi!

From the position where i continued i only get silence. But why? I can't
see the mistake...sorry.

                   _myBuffer.Write(buffer, length);

                    byte[] ringbuffer = new byte[length];
                    while (true)
                    {
                        int i = _myBuffer.Read(buffer, length, 0);
                        if (i > 0)
                        {
                            _fs.Write(ringbuffer, 0, i);
                         }
                        else
                        {
                            break;
                        }
                    }

Greetings,
Joe
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #9 on: 13 Aug '12 - 14:13 »
Reply with quoteQuote

To confirm whether the problem is in the appending, what happens if you record to a new file instead, ie. does the file contain sound? If not, perhaps you are not recording from the device/input that you want, and the BASS_RecordInit "device" parameter needs changing? You could try playing with the pre-compiled RECTEST.EXE example from the BASS package (C\BIN folder) to confirm what devices/inputs are available and if any sound can be captured from them.
Logged
Benchjoe
Posts: 13


« Reply #10 on: 17 Aug '12 - 06:49 »
Reply with quoteQuote

To confirm whether the problem is in the appending, what happens if you record to a new file instead, ie. does the file contain sound?

Yes, there is normal sound when i start recording from the beginning. Data comes into _myBuffer,
now some data comes out from the position i continued the recording: LOUD, scratching NOISE. Why?

RecordInit seems to work, there is no error.

Thanks!
Joe
« Last Edit: 23 Aug '12 - 07:22 by Benchjoe » Logged
Benchjoe
Posts: 13


« Reply #11 on: 23 Aug '12 - 07:24 »
Reply with quoteQuote

Quote from: Benchjoe

Yes, there is normal sound when i start recording from the beginning. Data comes into _myBuffer,
now some data comes out from the position i continued the recording: LOUD, scratching NOISE. Why?

RecordInit seems to work, there is no error.

Thanks!
Joe

Any idea from where this noise could come?
TIA,
Joe
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #12 on: 23 Aug '12 - 16:46 »
Reply with quoteQuote

Are you writing another WAVE header to the file? If so, you shouldn't do that. You need to update the file's existing headers instead (eg. increase the chunk lengths), and append the new sample data to the "data" chunk.
Logged
Benchjoe
Posts: 13


« Reply #13 on: 24 Aug '12 - 12:02 »
Reply with quoteQuote

I use this:

public void WaveHeaderReading(string spath)
        {
            FileStream fs = new FileStream(spath, FileMode.Open, FileAccess.Read);

            BinaryReader br = new BinaryReader(fs);
            length = (int)fs.Length - 8;
            fs.Position = 16;
            fmtlen = br.ReadInt32();

            fs.Position = 22;
            channels = br.ReadInt16();
            fs.Position = 24;
            samplerate = br.ReadInt32();
            fs.Position = 34;
            BitsPerSample = br.ReadInt16();
            DataLength = (int)fs.Length - 44;
            br.Close();
            fs.Close();

        }

        public void WaveHeaderWriting(string sPath)
        {
            FileStream fs = new FileStream(sPath, FileMode.Open, FileAccess.Write);

            BinaryWriter bw = new BinaryWriter(fs);
            fs.Position = 0;
            bw.Write(new char[4] { 'R', 'I', 'F', 'F' });

            bw.Write(length);

            bw.Write(new char[4] { 'W', 'A', 'V', 'E'});
            bw.Write(new char[4] { 'f', 'm', 't', ' ' });

            bw.Write((int)fmtlen);

            bw.Write((short)1);
            bw.Write(channels);

            bw.Write(samplerate);//int32 samplerate

            bw.Write((int)(samplerate * ((BitsPerSample * channels) / 8)));//byterate

            bw.Write((short)((BitsPerSample * channels) / 8));//Blockalign

            bw.Write((short)BitsPerSample);//bitspersample
            //extraparamsize 2bit
            bw.Write((short)1);


            fs.Position = 50;
            bw.Write(new char[4] { 'd', 'a', 't', 'a' });
            bw.Write(DataLength);
            bw.Close();
            fs.Close();
        }

TIA,
Joe
Logged
Benchjoe
Posts: 13


« Reply #14 on: 30 Aug '12 - 09:34 »
Reply with quoteQuote

Hi!

Before writing to the file i open it and jump to the end of file:

_fs = new FileStream(tbFile.Text, FileMode.Append, FileAccess.Write);
_fs.Seek(_fs.Length, SeekOrigin.Begin);

Or should i use a Binarywriter in the CallbackMethod? Is there a difference between Filestream and Binarywriter?

Greetings,
Joe
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #15 on: 30 Aug '12 - 14:18 »
Reply with quoteQuote

I'm not familiar with "Filestream" or "Binarywriter", so I'm afraid I can't advise on that stuff, but the basic process would be to append the new sample data to the end of the file's existing "data" chunk, and then update the length values in the "data" and "RIFF" chunk headers to reflect the new chunk/file lengths. You wouldn't write additional chunks/headers to the file.
Logged
Benchjoe
Posts: 13


« Reply #16 on: 11 Sep '12 - 12:16 »
Reply with quoteQuote

Hi!

Now i found out, that only one channel contains this loud scratching noise.
The other channel contains my recordings.

Maybe a stereo/mono problem...

Greetings,
Joe
« Last Edit: 11 Sep '12 - 13:27 by Benchjoe » Logged
radio42
Posts: 4012


« Reply #17 on: 11 Sep '12 - 13:33 »
Reply with quoteQuote

The difference between a .Net 'FileStream' and 'BinrayWriter' is e.g. explained here:
http://forums.asp.net/t/1767499.aspx/1

Bass.Net uses in the WaveWriter class a BinaryWriter with a FileStream, basically like this:
FileStream fs = new FileStream(<FileName>, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
...
bw.Write(...)

As Ian indicated, you can not simply append new sample data to an existing .wav file, as the sample data must be appended inside the "data" chunk of the wave file, plus the "RIFF" header chunk must be updated to reflect the new data chunk length.
A detailed wave format description can be e.g. found here:
http://tools.ietf.org/html/draft-ema-vpim-wav-00


Logged
Benchjoe
Posts: 13


« Reply #18 on: 11 Sep '12 - 14:41 »
Reply with quoteQuote

Hi Bernd!

As Ian indicated, you can not simply append new sample data to an existing .wav file, as the sample data must be appended inside the "data" chunk of the wave file, plus the "RIFF" header chunk must be updated to reflect the new data chunk length.
A detailed wave format description can be e.g. found here:
http://tools.ietf.org/html/draft-ema-vpim-wav-00

Thx, i tested Binarywriter vs. Filestream. With the same result.
I thought, that i have done this als Ian indicated. If the 'data' chunk is the last chunk in the file,
i can append the sample data and update the headers.

Greetings,
Joe
Logged
saga
Posts: 1365


« Reply #19 on: 11 Sep '12 - 14:51 »
Reply with quoteQuote

Actually, a WAV file may contain several data chunks, but software behaviour will probably differ largely wrt to this feature (most software will just read the first chunk).
Logged
Pages: [1] 2  All
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines