18 Jun '13 - 09:02 *
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: Simultaneous record and play from different devices  (Read 775 times)
dts350z
Posts: 17


« on: 26 May '12 - 18:17 »
Reply with quoteQuote

I want to record from one device, do some processing, and play from another. Currently these are in the same thread.

I'm doing:


// input is an audio device
// check the correct BASS was loaded
if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
Error("An incorrect version of BASS was loaded");
return 1;
}
/*
if (!BASS_RecordSetDevice(rec_dn)) {
sprintf_s(message,"Failed to set input audio device. Error: %d\n",BASS_ErrorGetCode());
MessageBox(NULL, TEXT((LPCSTR)message), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
return 1;
}
*/
if (!BASS_RecordInit(rec_dn)){
MessageBox(NULL, TEXT("Could not initialize input audio device"), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
return 1;
}
if (!BASS_RecordGetDeviceInfo(rec_dn, &rec_device_info)) {
MessageBox(NULL, TEXT("Could not get info for input audio device"), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
return 1;
}
rec_handle = BASS_RecordStart(44100, 2, BASS_SAMPLE_FLOAT,NULL,0);  //NULL or RecordingCallback
if (!rec_handle) {
MessageBox(NULL, TEXT("Could not start input device"), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
return 1;
}

(Note that BASS_RecordSetDevice fails with error 23 and is commented out because it's not used in rectest anyway)

with device 0

Available Audio Input Devices:

        0: Line 1 (Virtual Audio Cable)
        1: Microphone (Saffire Audio)
        2: U46 Ch12 (U46 Audio driver)
        3: U46 Ch34 (U46 Audio driver)
        4: U46 Ch56 (U46 Audio driver)
        5: U46 Multi-6 ch (U46 Audio drive

Available Audio Output Devices:

        -1: default device
        0: No sound
        1: Line 1 (Virtual Audio Cable)
        2: U46 Ch12 (U46 Audio driver)
        3: U46 Ch56 (U46 Audio driver)
        4: Speakers (U46 Audio driver)
        5: Speakers (Saffire Audio)
        6: Realtek Digital Output (Realtek High Definition Audio)
        7: U46 Ch34 (U46 Audio driver)
        100: ASIO ASIO 2.0 - ESI U46
        101: ASIO ASIO Avid Driver
        102: ASIO ASIO DirectX Full Duplex Driver
        103: ASIO ASIO4ALL v2
        104: ASIO Generic Low Latency ASIO Driver
        105: ASIO JackRouter
        106: ASIO ASIO Saffire

And trying to play back with device 4 (or other).

When I try to use a non ASIO device BASS_StreamCreate fails with error -1 (failed to start 16bit stream popup):

When I try to use an ASIO device, depending on the device, I get Error (0) can't initialize device, or a crash in the driver. All the playback code is working with input from a file (vs. recording)


if ( dn < 100 ) {

//if (floatable) BASS_StreamFree(floatable); // floating-point channels are supported!
if (floatable) {
if (chan=BASS_StreamCreate(sfinfo.samplerate,6,BASS_SAMPLE_FLOAT,STREAMPROC_PUSH,user)) {
BASS_ChannelGetInfo(chan,&bci);
y = initial_y + 5;
SetPos(0,y);
printf("%s\rStarted float stream with %d inputs and %d outputs\r",blankln,bci.chans, bi.speakers);
}
else {
sprintf_s(message,"Failed to start float stream. Error: %d\n",BASS_ErrorGetCode());
MessageBox(NULL, TEXT((LPCSTR)message), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
//printf("samplerate: %d channels: %d\n",sfinfo.samplerate, sfinfo.channels);
return 1;
}
}
else {
if (chan=BASS_StreamCreate(sfinfo.samplerate, sfinfo.channels,0,STREAMPROC_PUSH,user)) {
BASS_ChannelGetInfo(chan,&bci);
y = initial_y + 5;
SetPos(0,y);
printf("%s\rStarted 16 bit stream with %d inputs and %d outputs\r",blankln,bci.chans, bi.speakers);
}
else {
sprintf_s(message,"Failed to start 16 bit stream. Error: %d\n",BASS_ErrorGetCode());
MessageBox(NULL, TEXT((LPCSTR)message), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
//printf("samplerate: %d channels: %d\n",sfinfo.samplerate, sfinfo.channels);
return 1;
}

}
}
else {
floatable = 1; //Assume all ASIO drivers are floatable
if (floatable != 0) {

if (chan=BASS_StreamCreate(sfinfo.samplerate, sfinfo.channels,BASS_SAMPLE_FLOAT|BASS_STREAM_DECODE,STREAMPROC_PUSH,user)) {
BASS_ChannelGetInfo(chan,&bci);
y = initial_y + 5;
SetPos(0,y);
printf("%s\rStarted float stream with %d inputs and %d outputs\r",blankln,bci.chans, asio_info.outputs);
}
else {
sprintf_s(message,"Failed to start float stream. Error: %d ASIO Error: %d\n",BASS_ErrorGetCode(),BASS_ASIO_ErrorGetCode());
MessageBox(NULL, TEXT((LPCSTR)message), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
//printf("samplerate: %d channels: %d\n",sfinfo.samplerate, sfinfo.channels);
return 1;
}
}
else {
if (chan=BASS_StreamCreate(sfinfo.samplerate, sfinfo.channels,BASS_STREAM_DECODE,STREAMPROC_PUSH,user)) {
BASS_ChannelGetInfo(chan,&bci);
y = initial_y + 5;
SetPos(0,y);
printf("%s\rStarted 16 bit stream with %d inputs and %d outputs\r",blankln,bci.chans, asio_info.outputs);
}
else {
sprintf_s(message,"Failed to start 16 bit stream. Error: %d ASIO Error: %d\n",BASS_ErrorGetCode(),BASS_ASIO_ErrorGetCode());
MessageBox(NULL, TEXT((LPCSTR)message), TEXT("SpecCL"), MB_OK|MB_ICONEXCLAMATION);
//printf("samplerate: %d channels: %d\n",sfinfo.samplerate, sfinfo.channels);
return 1;
}

}

}

Do all the recording calls need to be in their own thread?

If so does calling BASS_ChannelGetData(rec_handle,inbuf,BASS_DATA_FLOAT) also have to be in the recording thread?

Right now I'm trying to do this:

while((sampsread = (!live)?sf_read_float(insndfile,inbuf,inbuflen):BASS_ChannelGetData(rec_handle,inbuf,BASS_DATA_FLOAT)) > 0){

where "live" is the switch between file based input (via libsndfile) and bass recording input.

Thanks
Z
Logged
dts350z
Posts: 17


« Reply #1 on: 28 May '12 - 02:45 »
Reply with quoteQuote


And how do you record with ASIO?
Logged
Ian @ un4seen
Administrator
Posts: 15352


« Reply #2 on: 28 May '12 - 15:54 »
Reply with quoteQuote

(Note that BASS_RecordSetDevice fails with error 23 and is commented out because it's not used in rectest anyway)

Error code 23 is BASS_ERROR_DEVICE, which means that the device number ("rec_dn") is invalid. In this case, the device number probably will be valid once BASS has enumerated the available devices, which will happen when you make a BASS_RecordInit or BASS_RecordGetDeviceInfo call. Note that BASS_RecordInit needs to be called to initialize a device before that device can be used in BASS_RecordSetDevice calls. A valid but uninitialized device will result in a BASS_ERROR_INIT error.

When I try to use a non ASIO device BASS_StreamCreate fails with error -1 (failed to start 16bit stream popup):

Error code -1 is BASS_ERROR_UNKNOWN, which unfortunately doesn't tell us much. I think it is most likely to be due to the DirectSound buffer creation failing for some unexpected reason. What are the "sfinfo.samplerate" and "sfinfo.channels" values in that call? Also, what Windows version are you using?

Do all the recording calls need to be in their own thread?

No.

And how do you record with ASIO?

Please have a look at the RECTEST example in the BASSASIO package for a little demonstration. You could also have a look at the LIVEFX examples from both the BASS and BASSASIO packages, as they're doing something similar to what you want; they process the input and send it to the output.
Logged
dts350z
Posts: 17


« Reply #3 on: 28 May '12 - 19:39 »
Reply with quoteQuote

Well the libsndfile stuff isn't if "!live", which means recording, but channels = 2 and sample rate = 44100.

All the bass stuff is working when I do use libsndfile to do file io, vs. recording.

I'm on windows 7 64bit, but working in 32 bit apps.

Thanks,
Z
Logged
dts350z
Posts: 17


« Reply #4 on: 28 May '12 - 19:48 »
Reply with quoteQuote

Ah, I see your point. I need to use valid values for the BASS play calls when I'm not using file io.

Logged
dts350z
Posts: 17


« Reply #5 on: 28 May '12 - 21:19 »
Reply with quoteQuote

OK so now my problem is I'm not getting anything back (except a zero return) from BASS_ChannelGetData, either with a specified length, or with the BASS_DATA_AVAILABLE flag, even though the recording started without errors.

If I switch to using a callback I get buffer lengths inside the callback, but I really wanted to use the BASS_ChannelGetData in a while loop as shown above.

Not sure how to debug from here, or how I would make a callback work with my existing flow. It seems to me that if you are using callback you have no choice but to process ALL the data, because new data will come in the next callback, where as I need to ask for a certain amount of data.

Logged
Ian @ un4seen
Administrator
Posts: 15352


« Reply #6 on: 29 May '12 - 13:31 »
Reply with quoteQuote

When recording without a RECORDPROC callback function, the recorded data is delivered via BASS_ChannelGetData, so what you want to do (call BASS_ChannelGetData in a loop) should be fine. Note BASS_ChannelGetData won't wait for data to become available; it will return whatever is currently available (up to the requested amount). So if you're repeatedly calling it without any delay, there are likely will be some calls that return nothing. Are you receiving nothing ever? If so, one possibility is that the recording is paused; are you using the BASS_RECORD_PAUSE flag or calling BASS_ChannelPause at all? What does BASS_ChannelIsActive say about it?
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines