Hi Ian,
I tried to PM you on this as it's very specific to my app and the features of BASS I'm trying to use are working fine. Although I got the response that the message was sent successfully it doesn't show up in my message space. So I'm posting it here on the public forum.
I’d like some advice on the following…
What I’m trying to achieve is to stream out in realtime, lossless audio, as I’m receiving it via an audio input on the users system. I think this should be possible, because internet radio streams exist in flac format, which can be played by players that support http lossless streams. Here are the steps I’ve taken so far…
1/ Use BASS_Record_Start with a callback function to receive the data: rChannel = BASS_RecordStart(DWORD(freq), DWORD(channels), 0, recordCallbackBridge, nil)
2/ Add an encoder to encode the incoming audio to flac: encoder = BASS_Encode_FLAC_Start(rChannel, nil, DWORD(BASS_ENCODE_AUTOFREE), nil, nil)
3/ The callback function is bridged from a c bridging function to my Swift function, as I found this necessary to get it working.
4/ Within the Swift callback, which I’ve named “myRecordProc”, I’m receving the data ok and can write it to a file if I wish. I could either write the file within the callback, or I could call BASS_Encode_FLAC_StartFile within the calling function to write the file.
5/ I don’t wish to write to a file though, instead as already mentioned I want to stream it out to an external player on the user’s lan that supports lossless http streams. No streaming is done outside of the user’s lan.
So far all appears to be working well as far as BASS is concerned.
Where I’m getting stuck is on how to stream it out to the external app, using the http server that’s built into my app. I already serve complete files via this server to the external player and that works well. What I’m attempting to do is modify the code I use to serve up the data for a complete file, to serve streams instead.
I’ve got as far as loading the URI to the external app. It loads; but I get the error “CB Flac lost sync” and the stream doesn’t commence playing.
I’m loading the URI within the callback function where the data is collected. What I don’t understand is how to get my http server to respond to requests for data as it arrives.
At the moment I’m incrementally increasing a Swift data variable as the data comes in, and passing the data to my function, which should respond to the http requests. I’m doing this in the hope that it would be served in chunks to the external player, and the player will determine how much of the data it wants to consume on each request. Once I’ve got a working solution in place I will want to remove any data that’s already been served. of course, otherwise my app’s memory usage would continue to mount.
I think I need to make use of the range header to control how much data is consumed on each request; but I’m failing to understand how to correctly make use of this.
Here are the headers I’ve attempted to use in the function that should handle the http requests…
response.headers["Accept-Ranges"] = "Bytes"
response.headers["Cache-Control"] = "no-store"
response.headers["Transfer-Encoding"] = "chunked"
// response.headers["Content-Length"] = "*"
response.headers["Content-Range"] = "0-12348/*"
response.headers["Content-Type"] = "audio/flac"
response.headers["X-Sample-Rate"] = "44100"
response.headers["X-Bits-Per-Sample"] = "16"
response.headers["X-Number-Of-Channels"] = "2"
// response.send(data:data)
value = true
print("Served amount", " " + String(data.count))
served = value
response.headers.append("Custom-Header", value: "HeaderValue")
do{
try response.send(data:data).end()
} catch {
print("No data sent")
}
next()
The “Content-Length” header is commented out, because if I include it the URI doesn’t even get loaded to the external player. The values in the “Content-Range” are just a guess. I have also tried setting the upper limit to the length of the incoming data buffer; but that didn’t work either. I’m also unclear as to whether to use “response.send(data:data).end on each request or just “response.send(data:data)”. I’ve tried both; but neither worked.
Perhaps I should be taking a different approach, and maybe there are other features of BASS I could be making use of, that would be more likely to work.
Any advice you can provide me with on this feature will be much appreciated. It’s something I would really like to get working before the first release of my app.
Thanks in advance.
Geoff