How to process an audio data from KiwiSDR on C#?
Hi everyone. I want to create a desktop application on c#. Now I can connect to the remote KiwiSDR and receive audio data, but i cant to process it correctly. What is audio format returned by Kiwi? Can anyone help me? My code below...
private ClientWebSocket socket;
public async Task ConnectAsync(string ip,RichTextBox rtb,KiwiAudioPlayer audioPlayer)
{
using var httpClient = new HttpClient();
socket = new ClientWebSocket();
var uri = new Uri("ws://172.12.54.44:8073/12345678/SND");
socket = new ClientWebSocket();
await socket.ConnectAsync(uri, CancellationToken.None);
// After connect
await SendCommand("SET auth t=kiwi p= ");
await SendCommand("SET AR OK in=12000 out=44100");
await SendCommand("SET squelch=0 max=0");
await SendCommand("SET genattn=0");
await SendCommand("SET gen=0 mix=-1");
await SendCommand("SET ident_user=kiwibob");
await SendCommand("SET mod=usb low_cut=0 high_cut=5000 freq=10100.000");
await SendCommand("SET agc=1 hang=0 thresh=-100 slope=6 decay=1000 manGain=20");
//should i use commands below???
//await SendCommand("SET samps=1");
//await SendCommand("SET compression=0");
await SendCommand("SET keepalive");
_ = StartKeepAliveLoop(); // запуск без очікування
var buffer = new byte[1024];
while (true)
{
var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
break;
}
if (result.MessageType == WebSocketMessageType.Binary)
{
//Here is my audio data (i suppose)
byte[] audioData = buffer.Take(result.Count).ToArray();
audioPlayer.AddAudio(audioData);
}
}
}
And my code for WaveOut:
class KiwiAudioPlayer
{
private BufferedWaveProvider provider;
private WaveOutEvent waveOut;
public KiwiAudioPlayer()
{
provider = new BufferedWaveProvider(new WaveFormat(12000, 16, 1));
provider.BufferLength = 12000 * 2 * 10; // довший буфер
provider.DiscardOnBufferOverflow = true;
waveOut = new WaveOutEvent();
waveOut.Init(provider);
waveOut.Play();
}
public void AddAudio(byte[] muLawBuffer)
{
provider.AddSamples(muLawBuffer, 0, muLawBuffer.Length);
}
public void Stop()
{
waveOut?.Stop();
waveOut?.Dispose();
}
}
Thank U!
Comments
I don't know anything about C#
Have a look at kiwiclient / kiwirecorder, written in Python. It does everything you need: https://github.com/jks-prv/kiwiclient
If you turn off audio compression you won't have to deal with the PCM coding.
Thank you vary much, but i still want to release it on C#.
You can still use C#. But the kiwiclient / kiwirecorder code will show you exactly what you have to do to use the Kiwi API and process the audio stream that is transported over the web socket.
You mean that kiwirecorder file consist a solution to my problem? So...I will check it and if it resolve i will answer you
I resolve it!Uhhhuuu....)
here is my c# code
correct settings
await SendCommand("SET auth t=kiwi p= ");
await SendCommand("SET AR OK in=12000 out=12000");
await SendCommand("SET squelch=0 max=0");
await SendCommand("SET genattn=0");
await SendCommand("SET gen=0 mix=-1");
await SendCommand("SET ident_user=kiwibob");
await SendCommand("SET mod=usb low_cut=0 high_cut=6000 freq=10100.000");
await SendCommand("SET agc=1 hang=0 thresh=-110 slope=6 decay=1000 manGain=50");
await SendCommand("SET compression=0");
await SendCommand("SET keepalive");
code for process byte array, received from KiwiSDR
var buffer = new byte[4096];
while (true)
{
var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
break;
}
if (result.MessageType == WebSocketMessageType.Binary)
{
if (Encoding.ASCII.GetString(buffer, 0, 3) == "SND")
{
int audioLength = result.Count - 16;
if (audioLength <= 0) return;
byte[] audioBytes = new byte[audioLength];
Array.Copy(buffer, 16, audioBytes, 0, audioLength);
// Convert from Big Endian to Little Endian
for (int i = 0; i < audioBytes.Length; i += 2)
{
byte tmp = audioBytes[i];
audioBytes[i] = audioBytes[i + 1];
audioBytes[i + 1] = tmp;
}
audioPlayer.provider.AddSamples(audioBytes, 0, audioBytes.Length);
}
}
Settings for WaveOut
class KiwiAudioPlayer
{
public BufferedWaveProvider provider;
private WaveOutEvent waveOut;
public KiwiAudioPlayer()
{
var waveFormat = new WaveFormat(12000,16, 1); // 12kHz, 16-bit, Mono
provider = new BufferedWaveProvider(waveFormat)
{
DiscardOnBufferOverflow = true
};
waveOut = new WaveOutEvent();
waveOut.Init(provider);
waveOut.Play();
}
public void AddAudioBytes(byte[] audioBytes)
{
provider.AddSamples(audioBytes, 0, audioBytes.Length);
}
public void Stop()
{
waveOut?.Stop();
waveOut?.Dispose();
}
}
Thank U!
Well, as I said initially, I don't know C#. So I cannot say if this code will work or not. You just need to try it and debug it.
I didn't know Python when I started working on kiwiclient / kiwirecorder, which was not written by me initially. I only modified it as I learned how it worked (as did many other people, most notably Christoph who is the author of the Kiwi TDoA algorithm).