Author Topic: how to stream a wav chunk to icecast server  (Read 230 times)

hungnt

  • Posts: 11
how to stream a wav chunk to icecast server
« on: 12 May '21 - 16:48 »
Hi guys,

As the title, can anyone can tell me how to stream a buffer of wav chunk to icecast server

A sample code provided would be appreciated.

Regards,
Hung

Ian @ un4seen

  • Administrator
  • Posts: 23879
Re: how to stream a wav chunk to icecast server
« Reply #1 on: 13 May '21 - 15:41 »
I don't think Icecast supports WAV data. Do you mean you want to encode the WAV data and send the result to the server? If so, if you set the BASSenc encoder/caster on a "push" stream (created with BASS_StreamCreate + STREAMPROC_PUSH) then you can use BASS_StreamPutData to send WAV/PCM data to it. Another option is to use BASS_Encode_Write, but note you will still need a stream to set the encoder/caster on then.

hungnt

  • Posts: 11
Re: how to stream a wav chunk to icecast server
« Reply #2 on: 14 May '21 - 07:55 »
Hi,

I use lame as encoder. The following is my code to init stream, and icecast also

Code: [Select]
public int init_stream()
{
    /*init stream handle */
    _recHandle = Bass.BASS_StreamCreatePush(44100, 1, BASSFlag.BASS_SAMPLE_8BITS, IntPtr.Zero);
    if (_recHandle == 0) return -1;

    /*Khởi tạo icecast instance*/
    IBaseEncoder encoder = null;
    IStreamingServer server = null;

    // create an encoder instance
    EncoderLAME _lame   = new EncoderLAME(_recHandle);           
    _lame.InputFile     = null;
    _lame.OutputFile    = null;
    _lame.LAME_Bitrate  = (int)this._Kbps;
    _lame.LAME_Mode     = EncoderLAME.LAMEMode.Default;
    _lame.LAME_TargetSampleRate = (int)EncoderLAME.SAMPLERATE.Hz_44100;
    _lame.LAME_Quality          = EncoderLAME.LAMEQuality.Quality;
    if (!_lame.EncoderExists) { return -2; }
    encoder = _lame;

    // now create the ICEcast instance using LAME
    _icecast = new ICEcast(_lame);
    _icecast.ServerAddress = this._server_ip;
    _icecast.ServerPort = this._server_port;
    _icecast.Username = "hungnt";
    _icecast.Password = "mk123456";
    _icecast.MountPoint = "/recording";
    _icecast.StreamName = "StreamName";
    _icecast.StreamGenre = "Test mic";
    _icecast.PublicFlag = true;
    _icecast.SongTitle = "Test mic";
    server = _icecast;

    // disconnect, if connected
    if (_broadCast != null && _broadCast.IsConnected)
    {
        _broadCast.Disconnect();
        _broadCast.Notification -= new BroadCastEventHandler(OnBroadCast_Notification);
    }
    _broadCast = null;
    GC.Collect();

    try
    {

        _broadCast = new BroadCast(_icecast);
        _broadCast.AutoReconnect = true;
        _broadCast.ReconnectTimeout = 5;
        _broadCast.Notification += new BroadCastEventHandler(OnBroadCast_Notification);
        if (_broadCast.AutoConnect() != true)
        {
            return -3; // icecast not connected
        }
        Bass.BASS_ChannelSetAttribute(_recHandle, BASSAttribute.BASS_ATTRIB_VOL, 0f);
        //Bass.BASS_ChannelPlay(_recHandle, false);

        return 0;
    }
    catch (Exception ex)
    {
        return -4; // icecast error!!           
    }


    return 0;
}

/*Here data is byte array which is converted to a base64 string that is encoded mic sound sent from web app */
public void play(byte[] arrayByte)
{

    Un4seen.Bass.Bass.BASS_StreamPutData(_recHandle,
                                            arrayByte,
                                            arrayByte.Length);

    Un4seen.Bass.Bass.BASS_ChannelPlay(_recHandle, false);

}

But the sound is very noise.

Do you see anything wrong in our code above?

Thanks



Ian @ un4seen

  • Administrator
  • Posts: 23879
Re: how to stream a wav chunk to icecast server
« Reply #3 on: 14 May '21 - 13:38 »
The push stream's sample format should match the format of the data that you're passing to BASS_StreamPutData. The BASS_StreamCreatePush call in the code above is setting 44100 Hz mono 8-bit. Is that correct? If not, modify it to match the data's format and see if you still get noise then. Also try unmuting the playback (don't set BASS_ATTRIB_VOL to 0) to see if it's noise even before it gets to the encoder/server.

hungnt

  • Posts: 11
Re: how to stream a wav chunk to icecast server
« Reply #4 on: 15 May '21 - 16:17 »
Hi Ian,

Thanks for your support , now we can hear the recording content very clearly!

But there are 3 things that we don't understand
1. The input data is chunk of audio/wav that we think data type should be 16bit, but we must use function stream_push for byte array ( not int16 array ) making the process succeed. If we convert byte array to int16 array then push it into the stream, the sound output very noise.
2. There is strange sound ( noise ) between every calling stream_push and stream_play for a received recorded packet (from web we periodically send recorded sound to backend, at backend program we decoded it then push it to icecast server).
3. Hearing via icecast is delayed approximately 20 second, is there any way to reduce this delay effectively because we make sure our internet connection very well.

Thanks,

hungnt

  • Posts: 11
Re: how to stream a wav chunk to icecast server
« Reply #5 on: 16 May '21 - 07:51 »
Hi Ian,

Thanks for your support , now we can hear the recording content very clearly!

But there are 3 things that we don't understand
1. The input data is chunk of audio/wav that we think data type should be 16bit, but we must use function stream_push for byte array ( not int16 array ) making the process succeed. If we convert byte array to int16 array then push it into the stream, the sound output very noise.
2. There is strange sound ( noise ) between every calling stream_push and stream_play for a received recorded packet (from web we periodically send recorded sound to backend, at backend program we decoded it then push it to icecast server).
3. Hearing via icecast is delayed approximately 20 second, is there any way to reduce this delay effectively because we make sure our internet connection very well.

Thanks,

Udated point 2. The crackle sound between playing calls is due to we use periodic timer to dequeue message. The timer period is bigger than audio timeslice. To avoid gap, we use the method sync of channel to set an event in endSync callback. In playback thread, we wait for the event, if received we will decide to read data from queue to ensure data read continuously.

 

Ian @ un4seen

  • Administrator
  • Posts: 23879
Re: how to stream a wav chunk to icecast server
« Reply #6 on: 17 May '21 - 17:17 »
1. The input data is chunk of audio/wav that we think data type should be 16bit, but we must use function stream_push for byte array ( not int16 array ) making the process succeed. If we convert byte array to int16 array then push it into the stream, the sound output very noise.

The format of the data passed to BASS_StreamPutData must match the format specified in the BASS_StreamCreate call. It doesn't necessarily have to be a "byte" array - it can be a short/int16 array for 16-bit data.

3. Hearing via icecast is delayed approximately 20 second, is there any way to reduce this delay effectively because we make sure our internet connection very well.

You could try reducing the "queue-size" and/or "burst-size" settings in the Icecast server config. Also make sure you aren't passing data to BASS_StreamPutData too quickly, creating a backlog of queued data. You can check the return value to help determine that, ie. check it isn't rising.

hungnt

  • Posts: 11
Re: how to stream a wav chunk to icecast server
« Reply #7 on: 23 May '21 - 18:00 »
Thank you for your support.  For icecast point, I will try do it then let you know the result