24 May '13 - 11:15 *
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]
  Reply  |  Print  
Author Topic: Windows Mobile Recording \ Network streaming  (Read 532 times)
Cory
Guest
« on: 22 Aug '12 - 07:42 »
Reply with quoteQuote

I’m looking to build an application based on BASS.NET that is to be used as a communications system over the network.
The basic idea is as follows
•   Each client will stream audio from it’s microphone input to the ‘server’
•   The server will be receiving upto 30 of these streams from various ‘clients’
•   The server will merge theses streams together to for a virtual chat room(Essentially a conference call)
•   The server will then stream this ‘virtual chat room’ back to each of the clients.
Now I have had some success with streaming audio across the network with the examples below, but the trick is that the ‘clients’ are going to be a mix of Windows Phones and Windows PC’s(Mostly Phones)

So my question is : What is going to be the best way to pickup the audio from the mic on a windows phone OS and have it stream to the server, I have seen a few different function available including  Bass.BASS_RecordStart and using the recoding callback function, but I don’t quite understand how that works.
I guess if  Bass.BASS_RecordStart works and it dumps the audio to the callback function then getting it across the network shouldn’t be too tricky?

One idea I had to break this project down into chunks was to build an application that records from the mic input, sends the data to the recording callback function which stores the data in some sort of buffer. In another thread, pickup the data from this buffer and play it.
This would essentially emulate both ends of my ‘client’ and ‘server’ model without the networking bit in the middle, once this is working as expected I can introduce the network streaming component.

Any tips or advise appreciated, even some links to similar threads on this forum would be appreciated.


Here are the pieces of VB.Net code that I have put together, they are not much good for my requirements but hopefully they will assist someone else looking to stream audio using BASS.NET
'Send the streaming audio out


strm = Bass.BASS_StreamCreateFile("Tornado.wav", 0, 0, BASSFlag.BASS_DEFAULT)
Dim encoder As Integer = AddOn.Enc.BassEnc.BASS_Encode_Start(strm, "lame -r -s 44100 -b 128 -",
                                       AddOn.Enc.BASSEncode.BASS_ENCODE_NOHEAD, Nothing, IntPtr.Zero)
Dim server = AddOn.Enc.BassEnc.BASS_Encode_ServerInit(encoder, "127.0.0.1:8001", 640, 640, AddOn.Enc.BASSEncodeServer.BASS_ENCODE_SERVER_DEFAULT, Nothing, IntPtr.Zero)
Bass.BASS_ChannelPlay(strm, False)



'Recieve the streaming audio and play it
Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)
Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PREBUF, 0)
Dim channel As Integer = Bass.BASS_StreamCreateURL("http://127.0.0.1:8001", 0, BASSFlag.BASS_STREAM_STATUS, Nothing, IntPtr.Zero)
Dim ThisError As Integer
ThisError = Bass.BASS_ErrorGetCode
Dim errorname As BASSError = ThisError
Bass.BASS_ChannelPlay(channel, False)


Logged
Ian @ un4seen
Administrator
Posts: 15270


« Reply #1 on: 22 Aug '12 - 15:34 »
Reply with quoteQuote

BASS is available for Windows CE, but it isn't currently available for Windows Phone OS, as that doesn't allow native code (note BASS.Net requires the native core BASS/add-on libraries). That is set to change with Windows Phone 8, so there will probably be a BASS version available for that in future, but if you need to support Windows Phone 7 too, then that may be a problem unless you can implement the client side without BASS/native code.
Logged
Coryh
Posts: 7


« Reply #2 on: 22 Aug '12 - 23:43 »
Reply with quoteQuote

Hi Ian,

I have been using Bass.net on my Windows Mobile devices, they are an older HTC diamon runing Windows Mobile 6.
Is this a supported configuration? Basic playback etc ahs been working on them no worries so far.
Logged
Ian @ un4seen
Administrator
Posts: 15270


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

Ah, OK. Windows Mobile is the predecessor of Windows Phone, but the 2 are quite different and software created for one won't run on the other. The Windows CE version of BASS will run on Windows Mobile (and PocketPC) devices, but not on Windows Phone devices. Do you only need to support Windows Mobile devices? If so, you should be fine to use BASS then. But you may have another obstacle in the encoding. I don't think the LAME encoder is available for Windows CE, and I'm not sure if there are any similar alternatives available either. Windows CE devices are generally fairly low spec and without hardware floating-point support, so not really ideal for encoding. What sort of sound quality are you looking for? There are voice codecs (eg. GSM 6.10) included with Windows Mobile that can be accessed via the BASSenc add-on (BASS_Encode_StartACM).
Logged
Coryh
Posts: 7


« Reply #4 on: 24 Aug '12 - 00:35 »
Reply with quoteQuote


Thanks for your replies Ian, Much appreciated.

Just Windows Mobile\Pocket PC support is fine at athis stage, I have a quantity of identical devices(HTC Diamond's) ready to go for this project.
Audio quality is not going to be too much of an issue, The plan is to use this system for communication between crew members in a live theater environment. It's not broadcast or recording quality so one of the builtin codecs should do fine.
I used LAME in my code above but that was just whilst playing with the encoder\decoder stuff.
What would be your suggestion(In broad terms) on how this system should work.
What is the best routine to use to get the audio from the Windows Mobile device back to the 'sevrer'
Logged
Ian @ un4seen
Administrator
Posts: 15270


« Reply #5 on: 27 Aug '12 - 13:59 »
Reply with quoteQuote

In that case, you could try using the Windows-provided GSM 6.10 codec. You will first need an appropriate format info block, which you can use BASS_Encode_GetACMFormat to generate. You can then use that in a BASS_Encode_StartACM call to setup the encoder on your recording channel. The encoded data will be received via an ENCODEPROC callback function, which you can have send the data to the central server, eg. via a TCP socket. If you would like to give it a go, here are some code snippets...

record=BASS_RecordStart(freq, 1, BASS_RECORD_PAUSE, RecordProc, NULL); // create a mono recording channel (paused)
// generate a GSM 6.10 format info block...
DWORD formlen=BASS_Encode_GetACMFormat(0, NULL, 0, NULL, 0); // get suggested format buffer size
void *gsmform=malloc(formlen); // allocate the format buffer
formlen=BASS_Encode_GetACMFormat(record, gsmform, formlen, NULL,
    MAKELONG(BASS_ACM_SUGGEST|BASS_ACM_RATE|BASS_ACM_CHANS,WAVE_FORMAT_GSM610)) // get the GSM 6.10 format info
BASS_Encode_StartACM(record, gsmform, 0, EncodeProc, NULL); // set a GSM 6.10 encoder on the recording
// setup connection with central server here, and send "gsmform" and "formlen" to initialize the decoder
BASS_ChannelPlay(record, 0); // resume the recording

...

BOOL CALLBACK RecordProc(HRECORD handle, const void *buffer, DWORD length, void *user)
{
return BASS_Encode_IsActive(handle); // continue recording if encoder is alive
}

void CALLBACK EncodeProc(HENCODE handle, DWORD channel, void *buffer, DWORD length, void *user)
{
// send "length" bytes of data in "buffer" to the central server
}

On the central server side, you would prepend the received data with a WAVE header (including the format info that the encoder used) and use BASS_StreamCreateFileUser to create a stream to decode/play it. It might look something like this...

// when the client/server connection is established
// generate a WAVE header (in a FIFO buffer) to tell the decoder what the data format is...
BYTE header1[20]={'R','I','F','F',0xff,0xff,0xff,0xff,'W','A','V','E','f','m','t',' ',formlen,0,0,0}; // WAVE file header
fifobuf->Write(header1, 20); // write it to the buffer
fifobuf->Write(gsmform, formlen); // add the format info block (sent by the client) to the buffer
BYTE header2[8]={'d','a','t','a',0xff,0xff,0xff,0xff}; // "data" chunk header
fifobuf->Write(header2, 8); // add it to the buffer
// create a stream to decode/play the data...
BASS_FILEPROCS fileprocs={FileCloseProc, FileLenProc, FileReadProc}; // callback table
stream=BASS_StreamCreateFileUser(STREAMFILE_BUFFERPUSH, 0, &fileprocs, 0); // create a "buffered push" stream to play the data
if (!stream) ... // failed, cancel it (close conection/etc)

...

void CALLBACK FileCloseProc(void *user)
{
// close the connection
}

QWORD CALLBACK FileLenProc(void *user)
{
return 0; // indeterminate length
}

DWORD CALLBACK FileReadProc(void *buffer, DWORD length, void *user)
{
return fifobuf->Read(buffer, length); // read up to "length" bytes of data
}

...

// when data is received from the client
BASS_StreamPutFileData(stream, data, datalen); // send the data to the stream

Please see the documentation for details on all of the aforementioned functions. To support multiple clients, you can use the "user" parameter to pass instance info to the callback functions. Once you have this stuff working, you can then go on to use the BASSmix add-on to mix/merge multiple streams into one, set an encoder on that, and send the result back to the clients.
Logged
Coryh
Posts: 7


« Reply #6 on: 28 Aug '12 - 00:50 »
Reply with quoteQuote

Brilliant, i'll give it a go!
Thanks
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines