MSHV-269
This commit is contained in:
609
MSHV_269/src/HvMsCore/linsound_in.cpp
Normal file
609
MSHV_269/src/HvMsCore/linsound_in.cpp
Normal file
@ -0,0 +1,609 @@
|
||||
#include "mscore.h"
|
||||
|
||||
#if defined _LINUX_
|
||||
//#include <QtGui>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include <pulse/simple.h>
|
||||
pa_simple *s_pulse_rx = NULL;
|
||||
|
||||
int MsCore::alsa_read_sound()
|
||||
{
|
||||
int count = 0;
|
||||
if (!is_pulse_a_in)
|
||||
{
|
||||
//////////////////////tova go zabavia ne znam kak /////////////////////////////////////////////////////////////
|
||||
static unsigned long long int time0 = 0; // times are in microseconds
|
||||
unsigned long long int time;
|
||||
struct timespec tspec, trem;
|
||||
|
||||
int timer;//, count;
|
||||
struct timeval tv;
|
||||
#if DEBUG > 2
|
||||
static unsigned long long int stime = 0;
|
||||
static int samples;
|
||||
static int calls=0, waits=0;
|
||||
#endif
|
||||
|
||||
// gettimeofday(&tv, NULL);
|
||||
tv.tv_sec = 200;
|
||||
tv.tv_usec = 200;
|
||||
time = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
||||
timer = rad_sound_state.data_poll_usec - (int)(time - time0); // time remaining from last poll
|
||||
if (timer > 1000)
|
||||
{ // see if enough time has elapsed
|
||||
// wait for the remainder of the poll interval
|
||||
tspec.tv_sec = 0;
|
||||
tspec.tv_nsec = timer * 1000;
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &tspec, &trem);
|
||||
#if DEBUG > 2
|
||||
waits++;
|
||||
}
|
||||
calls++;
|
||||
if (calls % 400 == 0)
|
||||
{
|
||||
#if DEBUG > 3
|
||||
printf("quisk_read_sound calls %d, waits %d, waits %.2f %%\n", calls, waits, 100.0 * waits / calls);
|
||||
#endif
|
||||
calls = waits = 0;
|
||||
}
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
// gettimeofday(&tv, NULL); // reset starting time value
|
||||
tv.tv_sec = 200;
|
||||
tv.tv_usec = 200;
|
||||
time0 = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
//////////////////////tova go zabavia ne znam kak /////////////////////////////////////////////////////////////
|
||||
|
||||
count = read_alsa();// read from ALSA soundcard
|
||||
|
||||
//2.57
|
||||
short *dat_t = new short[count+10];
|
||||
for (int j = 0; j < count; ++j)
|
||||
{
|
||||
if (sample_bytes == 2 || sample_bytes == 4) dat_t[j] = cSamples_l[j]/65536; //int to short
|
||||
else if (sample_bytes == 3) dat_t[j] = cSamples_l[j]/256; //int to short
|
||||
}
|
||||
ResampleAndFilter(dat_t,count);
|
||||
delete [] dat_t;
|
||||
//////////////////////tova go zabavia ne znam kak /////////////////////////////////////////////////////////////
|
||||
#if DEBUG > 3
|
||||
if (stime == 0)
|
||||
{
|
||||
stime = time0;
|
||||
samples = 0;
|
||||
}
|
||||
else if (time0 - stime > 5000000)
|
||||
{
|
||||
samples += nSamples;
|
||||
printf("sample rate %.2f\n", 1e6 * samples / (time0 - stime));
|
||||
stime = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
samples += nSamples;
|
||||
}
|
||||
#endif
|
||||
//////////////////////tova go zabavia ne znam kak /////////////////////////////////////////////////////////////
|
||||
}
|
||||
else
|
||||
{
|
||||
//int k = 0;
|
||||
//st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
|
||||
//num_bytes = st->sampc * st->sampsz;
|
||||
const int buf_c = 1024;//4096;//2048;
|
||||
|
||||
short buf[buf_c];
|
||||
int bufsize = buf_c * sizeof(short);
|
||||
//if (bufsize > buf_c) bufsize = buf_c;
|
||||
|
||||
// Record some data ...
|
||||
int error;
|
||||
if (pa_simple_read(s_pulse_rx, buf, bufsize, &error) < 0)
|
||||
{
|
||||
//fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
|
||||
//goto finish;
|
||||
return 0;
|
||||
}
|
||||
int cnt = bufsize / sizeof(short);
|
||||
|
||||
for (int i = 0; i<cnt; i += 2, count++)//chan_capt
|
||||
{
|
||||
short si = buf[i + channel_I];
|
||||
short sq = buf[i + channel_Q];
|
||||
/*int si,sq;
|
||||
memcpy((unsigned char *)&si + 1, buf + (i + channel_I) * 3, 3);
|
||||
memcpy((unsigned char *)&sq + 1, buf + (i + channel_Q) * 3, 3);*/
|
||||
//int16_t si = buf[i] + ((uint32_t)buf[i+1] << 8);
|
||||
//int16_t sq = buf[i+0] + ((uint32_t)buf[i+1] << 8);
|
||||
|
||||
if (si >= CLIP16 || si <= -CLIP16)
|
||||
quisk_overrange++; // assume overrange returns max int
|
||||
if (sq >= CLIP16 || sq <= -CLIP16)
|
||||
quisk_overrange++;
|
||||
|
||||
//ii = si << 16;
|
||||
//qq = sq << 16;
|
||||
|
||||
cSamples_l[count] = si;
|
||||
cSamples_r[count] = sq;
|
||||
}
|
||||
|
||||
//2.57
|
||||
short *dat_t = new short[count+10];
|
||||
for (int j = 0; j < count; ++j) dat_t[j] = cSamples_l[j];//int to short
|
||||
ResampleAndFilter(dat_t,count);
|
||||
delete [] dat_t;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int MsCore::read_alsa()
|
||||
{ // read sound samples from the ALSA soundcard
|
||||
int i;
|
||||
snd_pcm_sframes_t frames, avail;
|
||||
short si, sq;
|
||||
int ii, qq;
|
||||
int nSamples;
|
||||
|
||||
/*double c_l;
|
||||
double c_r;
|
||||
double dc_remove_l=0;
|
||||
double dc_remove_r=0;*/
|
||||
|
||||
#ifdef FIX_H101
|
||||
static short save_sq = 0;
|
||||
#endif
|
||||
|
||||
if (!hCapture)
|
||||
return -1;
|
||||
avail = 0;
|
||||
snd_pcm_delay(hCapture, &avail); // samples available in the capture buffer
|
||||
|
||||
nSamples = 0;
|
||||
if (avail > SAMP_BUFFER_SIZE / chan_capt) // limit read request to buffer size
|
||||
avail = SAMP_BUFFER_SIZE / chan_capt;
|
||||
switch (sample_bytes)
|
||||
{
|
||||
case 2:
|
||||
frames = snd_pcm_readi (hCapture, buffer2, avail); // read available samples
|
||||
if (frames == -EAGAIN)
|
||||
{ // no samples available
|
||||
break;
|
||||
}
|
||||
else if (frames <= 0)
|
||||
{ // error
|
||||
rad_sound_state.read_error++;
|
||||
snd_pcm_prepare (hCapture);
|
||||
snd_pcm_start (hCapture);
|
||||
break;
|
||||
}
|
||||
for (i = 0; frames; i += chan_capt, nSamples++, frames--)
|
||||
{
|
||||
si = buffer2[i + channel_I];
|
||||
sq = buffer2[i + channel_Q];
|
||||
if (si >= CLIP16 || si <= -CLIP16)
|
||||
quisk_overrange++; // assume overrange returns max int
|
||||
if (sq >= CLIP16 || sq <= -CLIP16)
|
||||
quisk_overrange++;
|
||||
ii = si << 16;
|
||||
#ifdef FIX_H101
|
||||
qq = save_sq << 16;
|
||||
save_sq = sq;
|
||||
#else
|
||||
qq = sq << 16;
|
||||
#endif
|
||||
cSamples_l[nSamples] = ii;
|
||||
cSamples_r[nSamples] = qq;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
frames = snd_pcm_readi (hCapture, buffer3, avail); // read available samples
|
||||
if (frames == -EAGAIN)
|
||||
{ // no samples available
|
||||
break;
|
||||
}
|
||||
else if (frames <= 0)
|
||||
{ // error
|
||||
rad_sound_state.read_error++;
|
||||
snd_pcm_prepare (hCapture);
|
||||
snd_pcm_start (hCapture);
|
||||
break;
|
||||
}
|
||||
for (i = 0; frames; i += chan_capt, nSamples++, frames--)
|
||||
{
|
||||
ii = qq = 0;
|
||||
if (convert_sample_bytes == ThreeLittle2Big)
|
||||
{
|
||||
*((unsigned char *)&ii ) = buffer3[(i + channel_I) * 3 + 2];
|
||||
*((unsigned char *)&ii + 1) = buffer3[(i + channel_I) * 3 + 1];
|
||||
*((unsigned char *)&ii + 2) = buffer3[(i + channel_I) * 3 ];
|
||||
*((unsigned char *)&qq ) = buffer3[(i + channel_Q) * 3 + 2];
|
||||
*((unsigned char *)&qq + 1) = buffer3[(i + channel_Q) * 3 + 1];
|
||||
*((unsigned char *)&qq + 2) = buffer3[(i + channel_Q) * 3 ];
|
||||
}
|
||||
else
|
||||
{ // ThreeLittle2Little
|
||||
memcpy((unsigned char *)&ii + 1, buffer3 + (i + channel_I) * 3, 3);
|
||||
memcpy((unsigned char *)&qq + 1, buffer3 + (i + channel_Q) * 3, 3);
|
||||
}
|
||||
if (ii >= CLIP32 || ii <= -CLIP32)
|
||||
quisk_overrange++; // assume overrange returns max int
|
||||
if (qq >= CLIP32 || qq <= -CLIP32)
|
||||
quisk_overrange++;
|
||||
cSamples_l[nSamples] = ii;
|
||||
cSamples_r[nSamples] = qq;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
frames = snd_pcm_readi (hCapture, buffer4, avail); // read available samples
|
||||
if (frames == -EAGAIN)
|
||||
{ // no samples available
|
||||
break;
|
||||
}
|
||||
else if (frames <= 0)
|
||||
{ // error
|
||||
rad_sound_state.read_error++;
|
||||
snd_pcm_prepare (hCapture);
|
||||
snd_pcm_start (hCapture);
|
||||
break;
|
||||
}
|
||||
for (i = 0; frames; i += chan_capt, nSamples++, frames--)
|
||||
{
|
||||
ii = buffer4[i + channel_I];
|
||||
qq = buffer4[i + channel_Q];
|
||||
if (ii >= CLIP32 || ii <= -CLIP32)
|
||||
quisk_overrange++; // assume overrange returns max int
|
||||
if (qq >= CLIP32 || qq <= -CLIP32)
|
||||
quisk_overrange++;
|
||||
cSamples_l[nSamples] = ii;
|
||||
cSamples_r[nSamples] = qq;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* for (i=0; i < nSamples; i++)
|
||||
{ // DC removal; R.G. Lyons page 553
|
||||
c_l = cSamples_l[i] + dc_remove_l * 0.95;
|
||||
cSamples_l[i] = c_l - dc_remove_l;
|
||||
dc_remove_l = c_l;
|
||||
|
||||
c_r = cSamples_r[i] + dc_remove_r * 0.95;
|
||||
cSamples_r[i] = c_r - dc_remove_r;
|
||||
dc_remove_r = c_r;
|
||||
|
||||
//cSamples_l[i]*=2;
|
||||
//cSamples_r[i]*=2;
|
||||
}*/
|
||||
return nSamples;
|
||||
}
|
||||
void MsCore::rad_open_sound()
|
||||
{
|
||||
rad_close_sound();
|
||||
|
||||
if (!is_pulse_a_in)
|
||||
{
|
||||
//rad_close_sound();
|
||||
|
||||
is_little_endian = 1; // Test machine byte order
|
||||
if (*(char *)&is_little_endian == 1)
|
||||
is_little_endian = 1;
|
||||
else
|
||||
is_little_endian = 0;
|
||||
|
||||
rad_sound_state.read_error = 0;
|
||||
rad_sound_state.write_error = 0;
|
||||
rad_sound_state.underrun_error = 0;
|
||||
rad_sound_state.interupts = 0;
|
||||
rad_sound_state.rate_min = rad_sound_state.rate_max = -99;
|
||||
rad_sound_state.chan_min = rad_sound_state.chan_max = -99;
|
||||
rad_sound_state.msg1[0] = 0;
|
||||
rad_sound_state.err_msg[0] = 0;
|
||||
rad_sound_state.bad_device = 1;
|
||||
// rad_sound_state.sdriq_audio_decim = 1.0; // No audio decimation
|
||||
|
||||
open_alsa_capture();
|
||||
|
||||
//qDebug()<<"------------"<<hCapture<<(bool)rad_sound_state.err_msg[0];
|
||||
if (rad_sound_state.err_msg[0])
|
||||
return; // error return
|
||||
if (hCapture)
|
||||
snd_pcm_start(hCapture);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The sample type to use
|
||||
/*is_little_endian = 1; // Test machine byte order
|
||||
if (*(char *)&is_little_endian == 1)
|
||||
is_little_endian = 1;
|
||||
else
|
||||
is_little_endian = 0;
|
||||
//is_little_endian = 0; // test*/
|
||||
|
||||
pa_sample_format_t Format_LE_BE = PA_SAMPLE_S16LE;
|
||||
//if (!is_little_endian) Format_LE_BE = PA_SAMPLE_S16BE;
|
||||
|
||||
pa_sample_spec ss;
|
||||
ss.format = Format_LE_BE;
|
||||
ss.rate = (uint32_t)in_sample_rate;
|
||||
ss.channels = 2;
|
||||
|
||||
int latency = 200000;//in useconds 1000000;
|
||||
pa_buffer_attr bufattr;
|
||||
//memset(&bufattr, 0, sizeof(bufattr));
|
||||
bufattr.fragsize = (uint8_t)-1;//=255
|
||||
bufattr.maxlength = pa_usec_to_bytes(latency,&ss);
|
||||
bufattr.minreq = pa_usec_to_bytes(0,&ss);
|
||||
bufattr.prebuf = (uint8_t)-1;//=255
|
||||
bufattr.tlength = pa_usec_to_bytes(latency,&ss);
|
||||
//qDebug()<<"-----------------"<<(uint8_t)-1;
|
||||
/*bufattr.maxlength = (uint32_t)-1;
|
||||
bufattr.tlength = (uint32_t)-1;
|
||||
bufattr.prebuf = (uint32_t)-1;
|
||||
bufattr.minreq = (uint32_t)-1;
|
||||
bufattr.fragsize = (uint32_t)pa_usec_to_bytes(1 * 10, &ss);*/
|
||||
/*bufattr.tlength = (uint32_t) latency;
|
||||
bufattr.minreq = (uint32_t) 1000;
|
||||
bufattr.maxlength = (uint32_t) -1;
|
||||
bufattr.prebuf = (uint32_t) -1;
|
||||
bufattr.fragsize = (uint32_t) latency;*/
|
||||
|
||||
int error;
|
||||
QString str_device_name = (QString)rad_sound_state.dev_capt_name;
|
||||
str_device_name.remove("pulse: ");
|
||||
if (str_device_name == "default")
|
||||
{
|
||||
//qDebug()<<"-----------------------"<<"default";
|
||||
if (!(s_pulse_rx = pa_simple_new(NULL, "MSHV", PA_STREAM_RECORD, NULL, "Receive", &ss, NULL, &bufattr, &error)))
|
||||
{
|
||||
//fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//char *ddevv = q-strdup(qPrintable(str_device_name));
|
||||
static char ddevv[128];//2.50
|
||||
strncpy(ddevv,str_device_name.toUtf8(),127);
|
||||
//qDebug()<<"-----------------------"<<ddevv;
|
||||
if (!(s_pulse_rx = pa_simple_new(NULL, "MSHV", PA_STREAM_RECORD, ddevv, "Receive", &ss, NULL, &bufattr, &error)))
|
||||
{
|
||||
//fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void MsCore::rad_close_sound()
|
||||
{
|
||||
if (hCapture)
|
||||
{
|
||||
snd_pcm_drop(hCapture);
|
||||
snd_pcm_close(hCapture);
|
||||
hCapture = NULL;
|
||||
}
|
||||
|
||||
strncpy (rad_sound_state.err_msg, CLOSED_TEXT, SC_SIZE_L);
|
||||
rad_sound_state.bad_device = 1;
|
||||
//qDebug()<<"close handles";
|
||||
|
||||
if (s_pulse_rx)
|
||||
{
|
||||
pa_simple_free(s_pulse_rx);
|
||||
//pa_simple_drain(s_pulse, NULL);
|
||||
s_pulse_rx = NULL;
|
||||
//usleep(5000000);
|
||||
}
|
||||
}
|
||||
void MsCore::open_alsa_capture()
|
||||
{ // Open the ALSA soundcard for capture and perhaps playback. Detect the
|
||||
// capture parameters and make the playback parameters the same.
|
||||
int chan_needed, err, dir;
|
||||
int poll_size;
|
||||
//unsigned int ui;
|
||||
snd_pcm_hw_params_t *hware;
|
||||
snd_pcm_sw_params_t *sware;
|
||||
snd_pcm_uframes_t frames;
|
||||
snd_pcm_format_t format;
|
||||
//qDebug()<<"format="<<hCapture<<rad_sound_state.dev_capt_name<<SND_PCM_STREAM_CAPTURE<<SND_PCM_NONBLOCK;
|
||||
if ((err = snd_pcm_open (&hCapture, rad_sound_state.dev_capt_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
|
||||
{
|
||||
//stop 2.26 qt5 gcc7.3.1
|
||||
//snprintf(rad_sound_state.err_msg, SC_SIZE_L, "Cannot open capture device %s (%s)",
|
||||
// rad_sound_state.dev_capt_name, snd_strerror (err));
|
||||
//qDebug()<<"------------"<<hCapture;
|
||||
return;
|
||||
}
|
||||
if ((err = snd_pcm_sw_params_malloc (&sware)) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Cannot allocate software parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
return;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_malloc (&hware)) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Cannot allocate hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
snd_pcm_sw_params_free (sware);
|
||||
return;
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_any (hCapture, hware)) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Cannot initialize capture parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
goto errend;
|
||||
}
|
||||
|
||||
/* UNAVAILABLE
|
||||
if ((err = snd_pcm_hw_params_set_rate_resample (hCapture, hware, 0)) < 0) {
|
||||
snprintf (quisk_sound_state.err_msg, SC_SIZE_L, "Cannot disable resampling (%s)\n",
|
||||
snd_strerror (err));
|
||||
goto errend;
|
||||
}
|
||||
*/
|
||||
rad_sound_state.bad_device = 0;
|
||||
// Get some parameters to send back
|
||||
if (snd_pcm_hw_params_get_rate_min(hware, &rad_sound_state.rate_min, &dir) != 0)
|
||||
rad_sound_state.rate_min = 0; // Error
|
||||
if (snd_pcm_hw_params_get_rate_max(hware, &rad_sound_state.rate_max, &dir) != 0)
|
||||
rad_sound_state.rate_max = 0; // Error
|
||||
if (snd_pcm_hw_params_get_channels_min(hware, &rad_sound_state.chan_min) != 0)
|
||||
rad_sound_state.chan_min= 0; // Error
|
||||
if (snd_pcm_hw_params_get_channels_max(hware, &rad_sound_state.chan_max) != 0)
|
||||
rad_sound_state.chan_max= 0; // Error
|
||||
// Set the capture parameters
|
||||
format = check_formats(hCapture, hware);
|
||||
//qDebug()<<"format================="<<format<<SND_PCM_FORMAT_UNKNOWN;
|
||||
if (format == SND_PCM_FORMAT_UNKNOWN)
|
||||
{
|
||||
strncpy (rad_sound_state.err_msg, "MSHV does not support your format.", SC_SIZE_L);
|
||||
goto errend;
|
||||
}
|
||||
//sample_rate = 44100;// rad_sound_state.sample_rate;
|
||||
//qDebug()<<sample_rate;
|
||||
if (snd_pcm_hw_params_set_rate (hCapture, hware, in_sample_rate, 0) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Can not set sample rate %d",
|
||||
in_sample_rate);
|
||||
goto errend;
|
||||
}
|
||||
if (snd_pcm_hw_params_set_access (hCapture, hware, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
|
||||
{
|
||||
strncpy(rad_sound_state.err_msg, "Interleaved access is not available", SC_SIZE_L);
|
||||
goto errend;
|
||||
}
|
||||
channel_I = rad_sound_state.channel_I;
|
||||
channel_Q = rad_sound_state.channel_Q;
|
||||
chan_needed = channel_I; // Set number of channels to highest index + 1
|
||||
if (chan_needed < channel_Q)
|
||||
chan_needed = channel_Q;
|
||||
chan_needed++;
|
||||
chan_capt = chan_needed;
|
||||
if (chan_capt < (int)rad_sound_state.chan_min)//hv
|
||||
chan_capt = rad_sound_state.chan_min;
|
||||
if (snd_pcm_hw_params_set_channels (hCapture, hware, chan_capt) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Can not set channels to %d", chan_capt);
|
||||
goto errend;
|
||||
}
|
||||
// Try to set a capture buffer larger than needed
|
||||
frames = in_sample_rate * 200 / 1000; // buffer size in milliseconds
|
||||
if (snd_pcm_hw_params_set_buffer_size_near (hCapture, hware, &frames) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Can not set capture buffer size");
|
||||
goto errend;
|
||||
}
|
||||
poll_size = in_sample_rate * rad_sound_state.data_poll_usec / 1000000;
|
||||
if (frames < (snd_pcm_uframes_t)poll_size * 3)
|
||||
{ // buffer size is too small, reduce poll time
|
||||
rad_sound_state.data_poll_usec = frames * 1000000 / in_sample_rate / 3;
|
||||
#if DEBUG
|
||||
printf("Reduced data_poll_usec %d for small sound capture buffer\n",
|
||||
rad_sound_state.data_poll_usec);
|
||||
#endif
|
||||
}
|
||||
#if DEBUG
|
||||
printf("Capture buffer size %d\n", (int)frames);
|
||||
if (frames > SAMP_BUFFER_SIZE / chan_capt)
|
||||
printf("Capture buffer exceeds size of sample buffers\n");
|
||||
#endif
|
||||
if ((err = snd_pcm_hw_params (hCapture, hware)) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Cannot set hw capture parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
goto errend;
|
||||
}
|
||||
if ((err = snd_pcm_sw_params_current (hCapture, sware)) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Cannot get software capture parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
goto errend;
|
||||
}
|
||||
if (chan_capt <= 0) // ima problem po niakoga go dava 0 igarmi hv
|
||||
chan_capt = 2; // ima problem po niakoga go dava 0 igarmi hv
|
||||
//qDebug()<<chan_capt;
|
||||
|
||||
if ((err = snd_pcm_prepare (hCapture)) < 0)
|
||||
{
|
||||
snprintf (rad_sound_state.err_msg, SC_SIZE_L, "Cannot prepare capture interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
goto errend;
|
||||
}
|
||||
// Now open the microphone
|
||||
//if (rad_sound_state.mic_dev_name[0])
|
||||
//open_microphone();
|
||||
|
||||
errend:
|
||||
snd_pcm_hw_params_free (hware);
|
||||
snd_pcm_sw_params_free (sware); ///qDebug()<<sample_bytes;//qDebug()<<"read";
|
||||
return;
|
||||
}
|
||||
|
||||
snd_pcm_format_t MsCore::check_formats(snd_pcm_t *h, snd_pcm_hw_params_t *hware)
|
||||
{
|
||||
snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
|
||||
sample_bytes = 0;
|
||||
|
||||
strncpy (rad_sound_state.msg1, "Available formats: ", SC_SIZE_L);
|
||||
if (snd_pcm_hw_params_test_format (h, hware, SND_PCM_FORMAT_S32) == 0)
|
||||
{
|
||||
if (!sample_bytes)
|
||||
{
|
||||
strncat(rad_sound_state.msg1, "*", SC_SIZE_L);
|
||||
sample_bytes = 4;
|
||||
format = SND_PCM_FORMAT_S32;
|
||||
}
|
||||
strncat(rad_sound_state.msg1, "S32 ", SC_SIZE_L);
|
||||
}
|
||||
if (snd_pcm_hw_params_test_format (h, hware, SND_PCM_FORMAT_U32) == 0)
|
||||
{
|
||||
strncat(rad_sound_state.msg1, "U32 ", SC_SIZE_L);
|
||||
}
|
||||
if (snd_pcm_hw_params_test_format (h, hware, SND_PCM_FORMAT_S24) == 0)
|
||||
{
|
||||
strncat(rad_sound_state.msg1, "S24 ", SC_SIZE_L);
|
||||
}
|
||||
if (snd_pcm_hw_params_test_format (h, hware, SND_PCM_FORMAT_U24) == 0)
|
||||
{
|
||||
strncat(rad_sound_state.msg1, "U24 ", SC_SIZE_L);
|
||||
}
|
||||
if (snd_pcm_hw_params_test_format (h, hware, SND_PCM_FORMAT_S24_3LE) == 0)
|
||||
{
|
||||
if (!sample_bytes)
|
||||
{
|
||||
strncat(rad_sound_state.msg1, "*", SC_SIZE_L);
|
||||
sample_bytes = 3;
|
||||
format = SND_PCM_FORMAT_S24_3LE;
|
||||
if (is_little_endian)
|
||||
convert_sample_bytes = ThreeLittle2Little; // Convert little endian to little
|
||||
else
|
||||
convert_sample_bytes = ThreeLittle2Big; // Convert little endian to big
|
||||
}
|
||||
strncat(rad_sound_state.msg1, "S24_3LE ", SC_SIZE_L);
|
||||
}
|
||||
if (snd_pcm_hw_params_test_format (h, hware, SND_PCM_FORMAT_S16) == 0)
|
||||
{
|
||||
if (!sample_bytes)
|
||||
{
|
||||
strncat(rad_sound_state.msg1, "*", SC_SIZE_L);
|
||||
sample_bytes = 2;
|
||||
format = SND_PCM_FORMAT_S16;
|
||||
}
|
||||
strncat(rad_sound_state.msg1, "S16 ", SC_SIZE_L);
|
||||
}
|
||||
if (snd_pcm_hw_params_test_format (h, hware, SND_PCM_FORMAT_U16) == 0)
|
||||
{
|
||||
strncat(rad_sound_state.msg1, "U16 ", SC_SIZE_L);
|
||||
}
|
||||
if (format == SND_PCM_FORMAT_UNKNOWN)
|
||||
strncat(rad_sound_state.msg1, "*UNSUPPORTED", SC_SIZE_L);
|
||||
else
|
||||
snd_pcm_hw_params_set_format (h, hware, format);
|
||||
|
||||
//qDebug()<<"Format"<<format<<sample_bytes;
|
||||
return format;
|
||||
}
|
||||
#endif
|
910
MSHV_269/src/HvMsCore/mscore.cpp
Normal file
910
MSHV_269/src/HvMsCore/mscore.cpp
Normal file
@ -0,0 +1,910 @@
|
||||
/* MSHV MsCore
|
||||
* Copyright 2015 Hrisimir Hristov, LZ2HV
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
|
||||
#include "mscore.h"
|
||||
#include <algorithm> // zaradi max(
|
||||
//#include <unistd.h>
|
||||
|
||||
using namespace std; // zaradi max(
|
||||
|
||||
//static const double IN_SAMPLE_RATE =11025.0;//no inposible hv rawfilter need to be off
|
||||
//static const double IN_SAMPLE_RATE =22050.0;
|
||||
static const double IN_SAMPLE_RATE_44100 =44100.0;
|
||||
static const double IN_SAMPLE_RATE_48000 =48000.0;
|
||||
|
||||
//#define FFT_SAMPLE_RATE 11025
|
||||
static const double ORG_SAMPLE_RATE_11025 = 11025.0;
|
||||
static const double ORG_SAMPLE_RATE_12000 = 12000.0;
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
//#include <QtGui>
|
||||
|
||||
MsCore::MsCore()
|
||||
{
|
||||
//facalcvd = 1.0;
|
||||
//f_adle_vd = false;
|
||||
ftci = false;//tci
|
||||
is_select_sound_device = true;
|
||||
//s_fft_cut_hi_frq = FFT_CUT_HI_FRQ;
|
||||
dec_busy = false;
|
||||
s_data_dsp_height = DATA_DSP_HEIGHT;
|
||||
|
||||
s_fft_end_frq = FFT_END_FRQ;
|
||||
s_fft_cut_low_frq = FFT_CUT_LOW_FRQ; //1.38 forget in soorry 1.37
|
||||
|
||||
s_data_width = DATA_WIDTH;
|
||||
s_data_height = DATA_HEIGHT;
|
||||
|
||||
count_rfesh_sm = 0;// zaradi bavnoto na jt65abc
|
||||
s_vdisp_speed = 2;
|
||||
s_freq_beg = 200;
|
||||
s_freq_end = 2200; //2000 hz bw
|
||||
f_disp_v_h = false;
|
||||
last_reset_sc_in = QDateTime::currentDateTimeUtc().toTime_t();
|
||||
s_in_level = 1.0;
|
||||
//period_time_sec = (int)STATIC_FFTW_PERIOD_TIME;
|
||||
//save_rms_points = 2;//vnimanie triabva da e pomalko ot ->RMS_BUF_SIZE w MsCore.h
|
||||
|
||||
g_read_snd = false;//true;
|
||||
sta_sto_flag = false;
|
||||
|
||||
draw_flag = false;
|
||||
|
||||
y_count = 0;
|
||||
saved_sinh_val = 0;
|
||||
compare_sinh_val = 0;
|
||||
sinh_sleep = 0;
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
s_mod_iden = 2;//HV important set to default mode fsk441
|
||||
fftw_sample_rate = (int)ORG_SAMPLE_RATE_11025;//HV important set to default mode fsk441 sample rate
|
||||
in_sample_rate = IN_SAMPLE_RATE_44100; //HV important set to default mode fsk441 sample rate
|
||||
koef_resample = (int)((in_sample_rate/ORG_SAMPLE_RATE_11025)-1);//HV important set to default mode fsk441 sample rate
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
THvRawFilter = new HvRawFilter(49,100.0,5000.0,false);//false -> LPF+HPF /* low pass filter and High pass filter */ for RX
|
||||
THvRawFilter->set_rate(fftw_sample_rate);//2.34
|
||||
|
||||
#if defined _LINUX_
|
||||
is_pulse_a_in = true;//2.65 default pulse
|
||||
hCapture = NULL;
|
||||
is_little_endian = 0;
|
||||
#endif
|
||||
|
||||
#if defined _LINUX_
|
||||
//strncpy(rad_sound_state.dev_capt_name, "hw:0,0", SC_SIZE_L); //2.65 default pulse
|
||||
strncpy(rad_sound_state.dev_capt_name, "pulse: default", SC_SIZE_L);
|
||||
#endif
|
||||
#if defined _WIN32_ //Primary Sound Capture Driver or "0"
|
||||
strncpy(rad_sound_state.dev_capt_name, "Primary Sound Capture Driver", SC_SIZE_L);//
|
||||
#endif
|
||||
s_count_resample = 0;
|
||||
|
||||
rad_sound_state.latency_millisecs = 100;
|
||||
rad_sound_state.data_poll_usec = 5000;
|
||||
rad_sound_state.channel_I = 0;//0 //standart->1 X-Fi->0
|
||||
rad_sound_state.channel_Q = 1;//1 //standart->0 X-Fi->1
|
||||
rad_sound_state.read_error = 0;
|
||||
rad_sound_state.write_error = 0;
|
||||
rad_sound_state.underrun_error = 0;
|
||||
rad_sound_state.interupts = 0;
|
||||
|
||||
FFT1 = FFT2 = ptWriteFft = NULL;
|
||||
count_ftt_window = 0;
|
||||
|
||||
bool p_read_snd = true;
|
||||
#if defined _WIN32_
|
||||
is_select_sound_device = select_device(true);//v1.46
|
||||
p_read_snd = is_select_sound_device;
|
||||
if (p_read_snd) p_read_snd = start_sound();
|
||||
#endif
|
||||
#if defined _LINUX_
|
||||
rad_open_sound();
|
||||
#endif
|
||||
|
||||
QTimer *timer_ref_ = new QTimer();
|
||||
connect(timer_ref_, SIGNAL(timeout()), this, SLOT(Refresh_t()));
|
||||
timer_ref_->start(5);//5ms refresh time
|
||||
|
||||
timer_fr_sound = new QTimer();
|
||||
connect(timer_fr_sound, SIGNAL(timeout()), this, SLOT(FastResetSoundCardIn_p()));
|
||||
|
||||
// SETUP APP FOR ALL MODES ///////////////////////////
|
||||
fftw_sample_rate=(int)ORG_SAMPLE_RATE_12000;
|
||||
record_app();//msk144
|
||||
|
||||
f_disp_v_h = true;
|
||||
fftw_sample_rate=(int)ORG_SAMPLE_RATE_12000;
|
||||
for (int i=1; i<10; i++)//1.51 10 9-speads //da se smeni na -> 6
|
||||
{
|
||||
s_vdisp_speed = i;
|
||||
//SetupSettings_((QString)rad_sound_state.dev_capt_name,QString("%1").arg(in_sample_rate),rad_sound_state.latency_millisecs,
|
||||
//rad_sound_state.data_poll_usec,rad_sound_state.channel_I,true);
|
||||
record_app(); //jt65abc
|
||||
}
|
||||
f_disp_v_h = false;
|
||||
s_vdisp_speed = 2;
|
||||
|
||||
fftw_sample_rate=(int)ORG_SAMPLE_RATE_11025;
|
||||
record_app();//jtms to jt6m
|
||||
// END SETUP APP FOR ALL MODES ///////////////////////////
|
||||
|
||||
usleep(2000);
|
||||
|
||||
//qDebug()<<((192000 * (( 1 * 16 ) / 8)) * 120 + 32);
|
||||
//qDebug()<<sizeof(double);
|
||||
g_read_snd = p_read_snd;//false;
|
||||
//SetStr_Sto(false);
|
||||
//qDebug()<<"CREATED";
|
||||
}
|
||||
MsCore::~MsCore()
|
||||
{
|
||||
delete THvRawFilter;
|
||||
}
|
||||
void MsCore::SetInLevel(int val)
|
||||
{
|
||||
//s_in_level = pow(10, ((double)(val - 50)/4)/20); // +- 12.5db
|
||||
s_in_level = pow(10, ((double)(val - 50)/2.5)/20.0);// +- 20db 1.78
|
||||
//qDebug()<<s_in_level;
|
||||
}
|
||||
void MsCore::close_sound()
|
||||
{
|
||||
if (ftci) return;//tci
|
||||
#if defined _WIN32_
|
||||
//qDebug()<<"TRAY StopSound";
|
||||
if (lpdCaptureBuff)//from v1.46
|
||||
{
|
||||
stop_sound();
|
||||
lpdCaptureBuff->Release();
|
||||
lpdCapture->Release();
|
||||
lpdCaptureBuff = NULL;//2.49 protection
|
||||
//lpdCapture = NULL;
|
||||
//if (lpdCaptureBuff) qDebug()<<"close lpdCaptureBuff true";
|
||||
//else qDebug()<<"close lpdCaptureBuff false";
|
||||
}
|
||||
#endif
|
||||
#if defined _LINUX_
|
||||
rad_close_sound();
|
||||
#endif
|
||||
}
|
||||
void MsCore::SetStr_Sto(bool flag)
|
||||
{
|
||||
g_read_snd = false;
|
||||
sta_sto_flag = flag;
|
||||
bool p_read_snd = true;
|
||||
#if defined _WIN32_
|
||||
if (!ftci)//tci
|
||||
{
|
||||
if (sta_sto_flag)
|
||||
{
|
||||
p_read_snd = select_device(false); //2.49 exception GUID is Changed
|
||||
if (p_read_snd) p_read_snd = start_sound();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lpdCaptureBuff)//1.46
|
||||
stop_sound();
|
||||
//if (lpdCaptureBuff) qDebug()<<"stop lpdCaptureBuff true";
|
||||
//else qDebug()<<"stop lpdCaptureBuff false";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g_read_snd = p_read_snd;
|
||||
|
||||
if (sta_sto_flag) // if app long time in stop fast reset sound card
|
||||
{
|
||||
FastResetSoundCardIn();
|
||||
}
|
||||
}
|
||||
void MsCore::SetMode(int mod_iden)
|
||||
{
|
||||
s_mod_iden = mod_iden;
|
||||
QString rate;
|
||||
|
||||
/*if (s_mod_iden == 0 || s_mod_iden == 7 || s_mod_iden == 8 || s_mod_iden == 9 ||
|
||||
s_mod_iden == 10 || s_mod_iden == 11 || s_mod_iden == 12 || s_mod_iden == 13 ||
|
||||
s_mod_iden == 14 || s_mod_iden == 15 || s_mod_iden == 16 || s_mod_iden == 17)//msk144 //jt65abc pi4 ft8 ft4 q65
|
||||
rate = QString("%1").arg((int)IN_SAMPLE_RATE_48000);
|
||||
else //if (s_mod_iden>0 && s_mod_iden<7)
|
||||
rate = QString("%1").arg((int)IN_SAMPLE_RATE_44100);*/
|
||||
if (s_mod_iden>0 && s_mod_iden<7) //2.65
|
||||
rate = QString("%1").arg((int)IN_SAMPLE_RATE_44100);
|
||||
else
|
||||
rate = QString("%1").arg((int)IN_SAMPLE_RATE_48000);
|
||||
|
||||
if (s_mod_iden == 7 || s_mod_iden == 8 || s_mod_iden == 9 || s_mod_iden == 10 || s_mod_iden == 11 || s_mod_iden == 13 ||
|
||||
s_mod_iden == 14 || s_mod_iden == 15 || s_mod_iden == 16 || s_mod_iden == 17)////jt65abc pi4 ft8 ft4 q65
|
||||
f_disp_v_h = true;
|
||||
else
|
||||
f_disp_v_h = false;
|
||||
|
||||
SetupSettings_((QString)rad_sound_state.dev_capt_name,rate,rad_sound_state.latency_millisecs,
|
||||
rad_sound_state.data_poll_usec,rad_sound_state.channel_I,true);
|
||||
}
|
||||
void MsCore::SetupSettings(QString dev_in_number,int latency,int card_buffer_polls,int channel)// QString,
|
||||
{
|
||||
//qDebug()<<"DN="<<dev_in_number<<in_sample_rate;
|
||||
if ((QString)rad_sound_state.dev_capt_name == dev_in_number && /*rad_sound_state.sample_rate == rate.toInt() &&*/
|
||||
rad_sound_state.latency_millisecs == latency && rad_sound_state.data_poll_usec == card_buffer_polls &&
|
||||
rad_sound_state.channel_I == channel)
|
||||
return;//za da ne garmi pod windows
|
||||
|
||||
SetupSettings_(dev_in_number,QString("%1").arg(in_sample_rate),latency,card_buffer_polls,channel,false);
|
||||
}
|
||||
void MsCore::record_app()
|
||||
{
|
||||
//qDebug()<<"Start record_app";
|
||||
int i, j;
|
||||
fftw_complex * pt;
|
||||
fft_data * pt1, * pt2;
|
||||
double graph_refresh;
|
||||
|
||||
//if (f_disp_v_h)
|
||||
//graph_refresh = 100.0;
|
||||
//else
|
||||
graph_refresh = 100.0; //7 refresha na fft hv zavisi ot samplerate
|
||||
|
||||
/*(about 800 to 1200 pixels) times the fft_size_multiplier. You can make fft_size_multiplier
|
||||
about 2 to 4, to make the FFT bins smaller if you have the processor power.*/
|
||||
////HV spriano //////////////////////////////////////
|
||||
//int fft_size_multiplier = 2;
|
||||
//fft_size = GRAPHIC_HEIGHT * fft_size_multiplier;
|
||||
//while (fft_size < (rad_sound_state.sample_rate * rad_sound_state.data_poll_usec / 1000000))
|
||||
//fft_size += GRAPHIC_HEIGHT;
|
||||
////HV spriano ////////////////////////////////////////
|
||||
|
||||
//fftw_sample_rate=ORG_SAMPLE_RATE_11025;
|
||||
double scale_x_inc_pix;
|
||||
if (f_disp_v_h) /// DATA_HEIGHT*2 -25 -19 -25<freq bara (- 10 malko ot dolnia disp)
|
||||
scale_x_inc_pix = (double)(((double)(s_data_height*2 -25 - 10)/(double)s_vdisp_speed) /(double)STAT_FFTW_V60_TIME);
|
||||
else
|
||||
scale_x_inc_pix = (double)((double)s_data_width /(double)STAT_FFTW_H30_TIME);// prez kolko piksela za sekunta
|
||||
|
||||
fft_size = (int)((double)fftw_sample_rate /(double)scale_x_inc_pix); // fft_size za da upalni celia ekran
|
||||
|
||||
//qDebug()<<"fft_size="<<fft_size<<"fft_size_end="<<fft_size/4;
|
||||
|
||||
average_count = max(1, int((double)fftw_sample_rate / (double)fft_size / graph_refresh));
|
||||
|
||||
/*s_scale = 2.0 / (double)average_count / (double)fft_size; //add 1.37 Divide by sample count
|
||||
s_scale /= pow(2.0, 31);//2.0, 31 //add 1.37 Normalize to max == 1*/
|
||||
|
||||
s_scale = 2.0 / (double)average_count / (double)fft_size; //add 1.37 Divide by sample count
|
||||
if (f_disp_v_h)//v1.51 corr for 9-v speeds
|
||||
{
|
||||
/*double k_correct = 0.25*(double)(s_vdisp_speed*s_vdisp_speed);
|
||||
s_scale = s_scale*((double)s_vdisp_speed*k_correct+(1.0-k_correct));
|
||||
s_scale /= pow(2.0, 14)*1.2;//2.46 5)*1.6=half*/
|
||||
|
||||
double k_correct = 0.25; //old
|
||||
s_scale = s_scale*((double)s_vdisp_speed*k_correct+(1.0-k_correct));
|
||||
s_scale /= pow(2.0, 23); //*1.0
|
||||
}
|
||||
else
|
||||
s_scale /= pow(2.0, 24)*1.2;//2.46 old pow(2.0, 31); //add 1.37 Normalize to max == 1
|
||||
//qDebug()<<"fft_size="<<fft_size;//<<average_count<<s_scale;//<<average_countd;
|
||||
|
||||
strncpy (rad_sound_state.err_msg, CLOSED_TEXT, SC_SIZE_L);
|
||||
count_fft = 0;
|
||||
pt1 = FFT1;
|
||||
pt2 = FFT2;
|
||||
FFT1 = FFT2 = ptWriteFft = NULL; // The callback may be active!
|
||||
// Create space for the fft
|
||||
if (pt1)
|
||||
{
|
||||
fftw_destroy_plan(pt1->plan_dsp);
|
||||
fftw_free(pt1->samples);
|
||||
free(pt1);
|
||||
}
|
||||
pt1 = (fft_data *)malloc(sizeof(fft_data)); //qDebug()<<"sizeof(fft_data)"<<sizeof(fft_data);
|
||||
pt1->status = EMPTY;
|
||||
pt1->index = 0;
|
||||
pt = pt1->samples = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (fft_size+52));//2.45 +50
|
||||
//qDebug()<<"pt1 1= creaate";
|
||||
//FFTW_ESTIMATE ni barzo
|
||||
//FFTW_ESTIMATE_PATIENT sredno
|
||||
//FFTW_MEASURE bavi no result
|
||||
//FFTW_PATIENT bavi mnogo
|
||||
//FFTW_EXHAUSTIVE bavi mnogo
|
||||
//org samo bavi
|
||||
//pt1->plan_dsp = fftw_plan_dft_1d(fft_size, pt, pt, FFTW_FORWARD, FFTW_MEASURE);
|
||||
pt1->plan_dsp = fftw_plan_dft_1d(fft_size, pt, pt, FFTW_FORWARD, FFTW_ESTIMATE_PATIENT);//1.35
|
||||
//qDebug()<<"pt1 1=end";
|
||||
// Create space to write samples while the first fft is in use
|
||||
if (pt2)
|
||||
{
|
||||
fftw_destroy_plan(pt2->plan_dsp);
|
||||
fftw_free(pt2->samples);
|
||||
free(pt2);
|
||||
}
|
||||
pt2 = (fft_data *)malloc(sizeof(fft_data));
|
||||
pt2->status = EMPTY;
|
||||
pt2->index = 0;
|
||||
pt = pt2->samples = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (fft_size+52));//2.45 +50
|
||||
//qDebug()<<"pt2 2= create";
|
||||
//FFTW_ESTIMATE ni barzo
|
||||
//FFTW_ESTIMATE_PATIENT sredno
|
||||
//FFTW_MEASURE bavi no result
|
||||
//FFTW_PATIENT bavi mnogo
|
||||
//FFTW_EXHAUSTIVE bavi mnogo
|
||||
//org samo bavi
|
||||
//pt2->plan_dsp = fftw_plan_dft_1d(fft_size, pt, pt, FFTW_FORWARD, FFTW_MEASURE);
|
||||
pt2->plan_dsp = fftw_plan_dft_1d(fft_size, pt, pt, FFTW_FORWARD, FFTW_ESTIMATE_PATIENT);//1.35
|
||||
//qDebug()<<"pt2 2="<<s_vdisp_speed;
|
||||
FFT1 = pt1;
|
||||
FFT2 = pt2;
|
||||
// Create space for the fft average and window
|
||||
if (fft_avg)
|
||||
free(fft_avg);
|
||||
if (fft_window)
|
||||
free(fft_window);
|
||||
|
||||
if (f_disp_v_h)
|
||||
{
|
||||
fft_avg = (double *) malloc(sizeof(double) * ((s_data_width)+50));////1.39 rem s_data_width/2 1.36 +20
|
||||
for (i = 0; i < s_data_width; i++)//1.39 rem s_data_width/2
|
||||
fft_avg[i] = 0;
|
||||
//qDebug()<<"fft_avg-------------------"<<((s_data_width/2)+20);
|
||||
}
|
||||
else
|
||||
{
|
||||
fft_avg = (double *) malloc(sizeof(double) * (s_data_height+20));//1.36 +20
|
||||
for (i = 0; i < s_data_height; i++)
|
||||
fft_avg[i] = 0;
|
||||
//qDebug()<<"fft_avg-------------------"<<s_data_height+20;
|
||||
}
|
||||
// same as nuttal_window but better
|
||||
fft_window = (double *) malloc(sizeof(double) * (fft_size+50));//1.36 +50
|
||||
for (i = 0, j = -fft_size / 2; i < fft_size; i++, j++)
|
||||
{
|
||||
if (0) // Hamming
|
||||
fft_window[i] = 0.54 + 0.46 * cos(2.0 * M_PI * j / fft_size);
|
||||
else // Hanning
|
||||
fft_window[i] = 0.5 + 0.5 * cos(2.0 * M_PI * j / fft_size);
|
||||
}
|
||||
//qDebug()<<"Stop record_app";
|
||||
}
|
||||
void MsCore::SetDecBusy(bool f)
|
||||
{
|
||||
dec_busy = f;
|
||||
}
|
||||
void MsCore::FastResetSoundCardIn()
|
||||
{
|
||||
if (!timer_fr_sound->isActive()) timer_fr_sound->start(220);//2.47
|
||||
}
|
||||
void MsCore::FastResetSoundCardIn_p()// for pure sound cards
|
||||
{
|
||||
//1min=60, 2min=120, 15min=900 ,30min=1800, 1h=3600, 1:30h=5400, 2h=7200
|
||||
unsigned int hh = QDateTime::currentDateTimeUtc().toTime_t();
|
||||
|
||||
if (hh < last_reset_sc_in + 1802)//1802=30:02 1800+2 2=seconds
|
||||
{
|
||||
//qDebug()<<"T Stop 1";
|
||||
timer_fr_sound->stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dec_busy)
|
||||
{
|
||||
//qDebug()<<"Decoder Busy";
|
||||
return;
|
||||
}
|
||||
//qDebug()<<"T Stop 2";
|
||||
timer_fr_sound->stop();
|
||||
|
||||
//qDebug()<<"Start FastReset====================================";
|
||||
|
||||
g_read_snd = false;//true; // stop reading
|
||||
|
||||
usleep(1000); //2.37 be6e 1000 1.33=no 20ms in sdr 1.34 // triabva da e mnogo pove4e otkolkoto e na loop
|
||||
|
||||
close_sound();
|
||||
|
||||
usleep(2000); //1.33=1000 1.34=2000 wait hardware to clear buffers
|
||||
|
||||
THvRawFilter->set_rate(fftw_sample_rate); //2.34
|
||||
|
||||
bool p_read_snd = true;
|
||||
#if defined _WIN32_
|
||||
if (!ftci) //tci
|
||||
{
|
||||
p_read_snd = select_device(true);
|
||||
if (p_read_snd) p_read_snd = start_sound();
|
||||
}
|
||||
#endif
|
||||
#if defined _LINUX_
|
||||
if (!ftci) //tci
|
||||
{
|
||||
rad_open_sound();
|
||||
}
|
||||
#endif
|
||||
|
||||
record_app(); //fftw
|
||||
|
||||
usleep(2000); //1.33=no 1.34 wait fftw
|
||||
|
||||
last_reset_sc_in = hh;
|
||||
g_read_snd = p_read_snd; // start reading
|
||||
//qDebug()<<"End FastReset=================================="<<QDateTime::currentDateTimeUtc().toString("hh:mm:ss");
|
||||
}
|
||||
static int tci_read_ = 0; //2.58 0=stop 1=buff 2=read
|
||||
void MsCore::SetupSettings_(QString dev_in_number, QString sample_rate, int latency, int card_buffer_polls,
|
||||
int channel,bool imidiatly)
|
||||
{
|
||||
if (!imidiatly)
|
||||
{
|
||||
if ((QString)rad_sound_state.dev_capt_name == dev_in_number && in_sample_rate == sample_rate.toInt() &&
|
||||
rad_sound_state.latency_millisecs == latency && rad_sound_state.data_poll_usec == card_buffer_polls &&
|
||||
rad_sound_state.channel_I == channel)
|
||||
return;//za da ne garmi pod windows
|
||||
}
|
||||
|
||||
g_read_snd = false;//true; // stop reading
|
||||
|
||||
usleep(1000); //2.37 be6e=1000 1.33=no in sdr 20ms // 1.34
|
||||
|
||||
close_sound();
|
||||
|
||||
usleep(2000); //1.33=yes 1.34 wait hardware to clear buffers
|
||||
|
||||
//msk144 //jt65abc pi4 ft8 ft4 q65
|
||||
/*if (s_mod_iden == 0 || s_mod_iden == 7 || s_mod_iden == 8 || s_mod_iden == 9 || s_mod_iden == 10 ||
|
||||
s_mod_iden == 11 || s_mod_iden == 12 || s_mod_iden == 13 ||
|
||||
s_mod_iden == 14 || s_mod_iden == 15 || s_mod_iden == 16 || s_mod_iden == 17)
|
||||
{
|
||||
fftw_sample_rate = (int)ORG_SAMPLE_RATE_12000;
|
||||
in_sample_rate = sample_rate.toInt();
|
||||
koef_resample = (int)((in_sample_rate/(int)ORG_SAMPLE_RATE_12000)-1);
|
||||
}
|
||||
else //if (s_mod_iden>0 && s_mod_iden<7)
|
||||
{
|
||||
fftw_sample_rate = (int)ORG_SAMPLE_RATE_11025;
|
||||
in_sample_rate = sample_rate.toInt();
|
||||
koef_resample = (int)((in_sample_rate/(int)ORG_SAMPLE_RATE_11025)-1);
|
||||
}*/
|
||||
if (s_mod_iden>0 && s_mod_iden<7) //2.65
|
||||
{
|
||||
fftw_sample_rate = (int)ORG_SAMPLE_RATE_11025;
|
||||
in_sample_rate = sample_rate.toInt();
|
||||
koef_resample = (int)((in_sample_rate/(int)ORG_SAMPLE_RATE_11025)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fftw_sample_rate = (int)ORG_SAMPLE_RATE_12000;
|
||||
in_sample_rate = sample_rate.toInt();
|
||||
koef_resample = (int)((in_sample_rate/(int)ORG_SAMPLE_RATE_12000)-1);
|
||||
}
|
||||
|
||||
//for pulse audio max is 512 ???
|
||||
strncpy(rad_sound_state.dev_capt_name,dev_in_number.toUtf8(),127); //127 2.37 be6e SC_SIZE_L
|
||||
//if ((QString)rad_sound_state.dev_capt_name==dev_in_number)
|
||||
//qDebug()<<"mscore="<<(QString)rad_sound_state.dev_capt_name<<dev_in_number;
|
||||
QString str_device_name = (QString)rad_sound_state.dev_capt_name;
|
||||
if (str_device_name=="TCI Client Input") ftci = true;
|
||||
else ftci = false;
|
||||
tci_read_ = 0; //2.58
|
||||
|
||||
rad_sound_state.latency_millisecs = latency;//50 be6e hv 50-300
|
||||
rad_sound_state.data_poll_usec = card_buffer_polls;
|
||||
if (channel == 0)
|
||||
{
|
||||
rad_sound_state.channel_I = 0;
|
||||
//rad_sound_state.channel_Q = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rad_sound_state.channel_I = 1;
|
||||
//rad_sound_state.channel_Q = 0;
|
||||
}
|
||||
|
||||
THvRawFilter->set_rate(fftw_sample_rate);//2.34
|
||||
|
||||
bool p_read_snd = true;
|
||||
#if defined _WIN32_
|
||||
if (!ftci) //tci
|
||||
{
|
||||
p_read_snd = select_device(true);
|
||||
if (p_read_snd) p_read_snd = start_sound();
|
||||
}
|
||||
#endif
|
||||
#if defined _LINUX_
|
||||
if (str_device_name.mid(0,7)=="pulse: ") is_pulse_a_in = true;
|
||||
else is_pulse_a_in = false;
|
||||
if (!ftci) //tci
|
||||
{
|
||||
rad_open_sound();
|
||||
int c_retry = 0;
|
||||
if (!is_pulse_a_in && !hCapture)
|
||||
{
|
||||
while (!hCapture)
|
||||
{
|
||||
usleep(100000);
|
||||
rad_open_sound();
|
||||
c_retry++;
|
||||
if (c_retry>120) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
record_app(); // fftw
|
||||
|
||||
usleep(2000); //1.33=yes 1.34 wait fftw
|
||||
|
||||
last_reset_sc_in = QDateTime::currentDateTimeUtc().toTime_t();// reset time for fast reset
|
||||
g_read_snd = p_read_snd;//false; // start reading
|
||||
//qDebug()<<"GrandReset";
|
||||
}
|
||||
#define TCIBUFRX_LIM 385024 //=8sec =385024
|
||||
#define TCIBUFRX TCIBUFRX_LIM + 16450 //sample is 4096 max from network +=16384
|
||||
static short tci_raw2_0[TCIBUFRX]; //mono
|
||||
static int tci_cr2_0 = 0;
|
||||
int _GetRxAudioReadTci_()
|
||||
{
|
||||
return tci_read_;
|
||||
}
|
||||
void _SetRxAudioTci_(short *raw2,int cr2) //sample is 4096
|
||||
{
|
||||
//qDebug()<<"tci_cr2_0"<<tci_cr2_0;
|
||||
if (tci_cr2_0 < TCIBUFRX_LIM)
|
||||
{
|
||||
for (int i = 0; i < cr2; ++i) tci_raw2_0[i+tci_cr2_0] = raw2[i];
|
||||
tci_cr2_0 += cr2;
|
||||
}
|
||||
tci_read_ = 2;
|
||||
}
|
||||
void MsCore::ReadTci()
|
||||
{
|
||||
tci_read_ = 1;
|
||||
static short tci_raw2_1[TCIBUFRX];
|
||||
int count = 0;
|
||||
for (int i = 0; i < tci_cr2_0; ++i)
|
||||
{
|
||||
tci_raw2_1[count] = tci_raw2_0[i];
|
||||
count++;
|
||||
}
|
||||
tci_cr2_0 = 0; // frre input buffer
|
||||
ResampleAndFilter(tci_raw2_1,count); //2.57
|
||||
}
|
||||
void MsCore::ResampleAndFilter(short *rawm,int crawm) //2.57
|
||||
{
|
||||
static short dat_tt[130000]; //12000*10=120000 max=10sec 120000+12000=132000
|
||||
int limit = 120000*(koef_resample+1);
|
||||
if (crawm > limit) crawm = limit;
|
||||
int k = 0;
|
||||
for (int i = 0; i < crawm; ++i)
|
||||
{
|
||||
if (s_count_resample==koef_resample)
|
||||
{
|
||||
double data_l = THvRawFilter->band_l((double)rawm[i]);
|
||||
dat_tt[k]=(short int)(data_l*s_in_level);
|
||||
s_count_resample = 0;
|
||||
k++;
|
||||
}
|
||||
else
|
||||
s_count_resample++;
|
||||
}
|
||||
ReciveData(dat_tt,k,false);
|
||||
//if (k>1024) qDebug()<<"FREEZE="<<k;
|
||||
//if (k>1024) qDebug()<<k<<crawm<<limit<<TCIBUFRX_LIM<<TCIBUFRX;
|
||||
//if (k>1024) printf("12KHz=%d, 48KHz=%d, limit48KHz=%d,\n",k,crawm,limit);
|
||||
}
|
||||
void MsCore::ReciveData(short *dat,int count,bool ffopen)
|
||||
{
|
||||
|
||||
emit Set_Raw(dat,count,ffopen); //1.27 psk rep fopen bool true false no file open
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
short in_dat = dat[i];
|
||||
audiobuffer[count_ftt_window] = in_dat;//*fac;
|
||||
if (count_ftt_window >= fft_size-1)// i < fft_size 1.29 for this -1
|
||||
{
|
||||
decode_fft_size_samples(audiobuffer, fft_size); // i < fft_size 1.29
|
||||
//qDebug()<<"count="<<fft_size;
|
||||
count_ftt_window = 0;
|
||||
}
|
||||
else
|
||||
count_ftt_window++;
|
||||
|
||||
buf_samp_sm[count_rfesh_sm] = in_dat;
|
||||
if (count_rfesh_sm >= 450-1)// max 500 v1.36
|
||||
{
|
||||
count_rfesh_sm = 0;
|
||||
double sum(0);
|
||||
//double val;
|
||||
int smiter = 0;
|
||||
for (int x = 0; x < 450; ++x)
|
||||
{
|
||||
double val = fabs(buf_samp_sm[x]);
|
||||
sum += val;
|
||||
}
|
||||
sum /= 450.0;
|
||||
double log0 = sqrt(sum);
|
||||
if (log0<1.0) log0=1.0; //2.58
|
||||
smiter = abs(int(log(log0)*20.0)); //qDebug()<<"count="<<sum<<log0<<log(log0);
|
||||
emit Sed_SMeter(smiter);// zaradi bavnoto na jt65abc
|
||||
}
|
||||
else
|
||||
count_rfesh_sm++;
|
||||
}
|
||||
}
|
||||
//max fft_size= 24452 to 1.54
|
||||
void MsCore::decode_fft_size_samples(short *data_mono, int count)
|
||||
{
|
||||
//inportant hv -> count==fft_size
|
||||
//double sum(0);
|
||||
//double val;
|
||||
//int smiter = 0;
|
||||
//qDebug()<<count;
|
||||
//qDebug()<<SAMP_BUFFER_PRE_BUFF;
|
||||
//HV VNIMANIE ako iskam s razli4ni samplerate triabva da se saobrazia s whodnite
|
||||
//GRAPHIC_WIDTH, period_time_sec, sample_rate i sled towa revord_app()
|
||||
|
||||
static int playSilence = 0;
|
||||
fft_data * ptFft;
|
||||
|
||||
//qDebug()<<count;
|
||||
|
||||
/* check for space, then put samples into the fft input array */
|
||||
if (! ptWriteFft)
|
||||
{ // wait for an empty fft to become available
|
||||
if (FFT1 && FFT1->status == EMPTY)
|
||||
{
|
||||
FFT1->status = FILLING;
|
||||
FFT1->index = 0;
|
||||
ptWriteFft = FFT1;
|
||||
}
|
||||
else if (FFT2 && FFT2->status == EMPTY)
|
||||
{
|
||||
FFT2->status = FILLING;
|
||||
FFT2->index = 0;
|
||||
ptWriteFft = FFT2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!playSilence && ptWriteFft)
|
||||
{ // write samples to fft data array
|
||||
double sum(0);
|
||||
int smiter = 0;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
//part of smiter
|
||||
if (!f_disp_v_h)
|
||||
{
|
||||
double val = fabs(data_mono[i]);
|
||||
sum += val;
|
||||
}
|
||||
|
||||
ptWriteFft->samples[ptWriteFft->index] = ((double)data_mono[i]*0.01);//2.46
|
||||
//if (ptWriteFft->index >= fft_size-1)
|
||||
//qDebug()<<"ptWriteFft->index"<<ptWriteFft->index;
|
||||
if (++(ptWriteFft->index) >= fft_size)
|
||||
{ // check sample count
|
||||
ptWriteFft->status = READY; // ready to run fft
|
||||
if (ptWriteFft == FFT1)
|
||||
{ // switch to other fft
|
||||
ptFft = FFT2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptFft = FFT1;
|
||||
}
|
||||
if (ptFft->status == EMPTY)
|
||||
{ // continue writing samples
|
||||
ptFft->status = FILLING;
|
||||
ptFft->index = 0;
|
||||
ptWriteFft = ptFft;
|
||||
}
|
||||
else
|
||||
{ // no place to write samples
|
||||
ptWriteFft = NULL;
|
||||
fft_error++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//part of smiter
|
||||
if (count==0) count=1;
|
||||
sum /= count;
|
||||
double log0 = sqrt(sum);
|
||||
if (log0<1.0) log0=1.0;//2.58
|
||||
smiter = abs(int(log(log0)*20.0));
|
||||
Get_Graph(smiter);
|
||||
// qDebug()<<"period_time_sec";
|
||||
}
|
||||
}
|
||||
void MsCore::SetVDispSpeed(int speed)
|
||||
{
|
||||
s_vdisp_speed = (10-speed);//1.51 10 9-speeds, 6
|
||||
//s_vdisp_speed = speed;
|
||||
SetupSettings_((QString)rad_sound_state.dev_capt_name,QString("%1").arg(in_sample_rate),rad_sound_state.latency_millisecs,
|
||||
rad_sound_state.data_poll_usec,rad_sound_state.channel_I,true);
|
||||
}
|
||||
void MsCore::setVDFftwStartStopFreq(int beg,int end)
|
||||
{
|
||||
s_freq_beg = beg;
|
||||
s_freq_end = end;
|
||||
}
|
||||
void MsCore::Get_Graph(int smiter)
|
||||
{
|
||||
int i, j, k, n;
|
||||
fft_data * ptFft;
|
||||
double y_scale[DATA_WIDTH+50];////1.39 rem s_data_width/2 1.37 max val
|
||||
double d2;
|
||||
|
||||
/// double *no_data = NULL;
|
||||
|
||||
//qDebug()<<DATA_WIDTH;
|
||||
//if (!PyArg_ParseTuple (args, ""))
|
||||
//return NULL;
|
||||
// Look for an fft ready to run. Throw the other away if there are two.
|
||||
if (FFT1 && FFT1->status == READY)
|
||||
{
|
||||
ptFft = FFT1;
|
||||
if (FFT2 && FFT2->status == READY)
|
||||
FFT2->status = EMPTY;
|
||||
}
|
||||
else if (FFT2 && FFT2->status == READY)
|
||||
{
|
||||
ptFft = FFT2;
|
||||
if (FFT1 && FFT1->status == READY)
|
||||
FFT1->status = EMPTY;
|
||||
}
|
||||
else
|
||||
{ // No data yet
|
||||
//Py_INCREF(Py_None);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < fft_size; ++i) // multiply by window
|
||||
ptFft->samples[i] *= fft_window[i];
|
||||
//ptFft->samples[i] = ptFft->samples[i]*fft_window[i];
|
||||
|
||||
fftw_execute(ptFft->plan_dsp); // Calculate FFT
|
||||
// Average the fft data into the graph width
|
||||
|
||||
//double kavg = 0.0;//2.46
|
||||
if (f_disp_v_h)
|
||||
{
|
||||
//int s_freq_end = 2200; //2150hz
|
||||
//int s_freq_beg = 200; //200hz 1.0 koef
|
||||
double size_6000 = fft_size/2.0;
|
||||
int beg_size = ((double)s_freq_beg*size_6000)/((double)fftw_sample_rate/2.0);
|
||||
int end_size = ((double)s_freq_end*size_6000)/((double)fftw_sample_rate/2.0);
|
||||
double d_koef = (double)(end_size-beg_size)/(double)((double)s_data_width);//1.39 rem s_data_width/2
|
||||
bool retry = false;
|
||||
|
||||
for (i = 0, k = 0; k < s_data_width; k++)//1.39 rem s_data_width/2
|
||||
{
|
||||
int c_kk = 1;
|
||||
c6:
|
||||
if (!retry)//2.45
|
||||
{
|
||||
fft_avg[k] += cabs(ptFft->samples[i+beg_size]);
|
||||
//kavg += fft_avg[k];//2.46
|
||||
}
|
||||
else
|
||||
{
|
||||
retry = false;
|
||||
double p0 = cabs(ptFft->samples[i+beg_size]);
|
||||
double p1 = cabs(ptFft->samples[i+beg_size+1]);
|
||||
fft_avg[k] = (p0+p1)/2.0;
|
||||
//kavg += fft_avg[k];//2.46
|
||||
}
|
||||
|
||||
if ((double)i>(double)k*d_koef)// tova pri nedostig
|
||||
{
|
||||
retry = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if ((double)i<(double)k*d_koef)// towa kogato ima mnogo
|
||||
{
|
||||
c_kk++;
|
||||
goto c6;
|
||||
}
|
||||
fft_avg[k]=(fft_avg[k]/(double)c_kk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n = fft_size / s_data_height /2 ; //HV za positie and negative bez -> / 2
|
||||
if ( n == 0 )//HV za da risuva i pod 20 seconds ina4e n = 0 stava
|
||||
n=1;
|
||||
for (i = 0, k = 0; k < s_data_height; ++k)
|
||||
for (j = 0; j < n; ++j)
|
||||
fft_avg[k] += cabs(ptFft->samples[i++]);
|
||||
}
|
||||
//qDebug()<<"fft_avg="<<k;
|
||||
|
||||
ptFft->status = EMPTY;
|
||||
if (++count_fft < average_count)
|
||||
{
|
||||
//Py_INCREF(Py_None); // No data yet
|
||||
return;
|
||||
}
|
||||
// We have averaged enough fft's to return the graph data
|
||||
count_fft = 0;
|
||||
//tuple2 = PyTuple_New(DATA_WIDTH);
|
||||
|
||||
i = 0;
|
||||
|
||||
if (f_disp_v_h)
|
||||
i=(s_data_width)-1;//DATA_DSP_HEIGHT-0; //1.39 rem s_data_width/2
|
||||
else
|
||||
i=s_data_dsp_height-1;//DATA_DSP_HEIGHT-0;
|
||||
//i=(150-46)-1;
|
||||
|
||||
if (f_disp_v_h)
|
||||
{
|
||||
//kavg /= s_data_width; //qDebug()<<kavg;//qoter avg
|
||||
//if (kavg < 0.001) kavg = 0.001; // //2.46
|
||||
//double avg_alcvd = 0.0;
|
||||
for (k = 0; k < s_data_width; ++k)//1.39 rem s_data_width/2
|
||||
{
|
||||
d2 = log10(fft_avg[k] * s_scale); //d2 = log(fft_avg[k] * (s_scale))*0.5;
|
||||
//avg_alcvd += fabs(d2);
|
||||
if (d2 < -10)
|
||||
d2 = -10;
|
||||
fft_avg[k] = 0;
|
||||
y_scale[i] = (50.0 * d2);
|
||||
|
||||
if (i>0)//1.36 i>0 pazi ot -1
|
||||
i--;
|
||||
}
|
||||
//avg_alcvd /= (double)s_data_width;
|
||||
//RefrAlcVD(avg_alcvd);
|
||||
}
|
||||
else
|
||||
{
|
||||
//for (k = FFT_CUT_LOW_FRQ; k < FFT_END_FRQ; k++/*, i--*/)//34
|
||||
for (k = s_fft_cut_low_frq; k < s_fft_end_frq; ++k/*, i--*/)
|
||||
{
|
||||
d2 = log10(fft_avg[k] * s_scale);
|
||||
if (d2 < -10)
|
||||
d2 = -10;
|
||||
fft_avg[k] = 0;
|
||||
y_scale[i] = (50.0 * d2);// 50.0 <- max display is 501
|
||||
|
||||
if (i>0)//1.36 i>0 pazi ot -1
|
||||
i--;
|
||||
}
|
||||
}
|
||||
//qDebug()<<"mmmmmmmmmmmmmmmmmmmmmmmmmmm";
|
||||
emit Set_Graph(y_scale, smiter);
|
||||
//delete y_scale;//rem 1.37
|
||||
}
|
||||
void MsCore::Refresh_t()
|
||||
{
|
||||
if (sta_sto_flag && g_read_snd)
|
||||
{
|
||||
if (ftci)//tci
|
||||
{
|
||||
if (tci_read_ == 0)
|
||||
{
|
||||
tci_cr2_0 = 0;
|
||||
tci_read_ = 1;
|
||||
}
|
||||
if (tci_read_ == 2) ReadTci();
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined _WIN32_
|
||||
ReadData();
|
||||
#endif
|
||||
#if defined _LINUX_
|
||||
alsa_read_sound();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
tci_read_ = 0;
|
||||
|
||||
emit Refresh_time();
|
||||
}
|
||||
|
299
MSHV_269/src/HvMsCore/mscore.h
Normal file
299
MSHV_269/src/HvMsCore/mscore.h
Normal file
@ -0,0 +1,299 @@
|
||||
/* MSHV
|
||||
*
|
||||
* By Hrisimir Hristov - LZ2HV
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
|
||||
#ifndef MSCORE_H
|
||||
#define MSCORE_H
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
//#include <QtGui>
|
||||
|
||||
#include <QObject>
|
||||
#include <math.h> //los
|
||||
//#include <stdlib.h> //abs
|
||||
//#include <unistd.h>
|
||||
//#include <iostream>
|
||||
#include <unistd.h>//usleep x86_64
|
||||
//using namespace std;
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
//#include "../../../DirectX90c/include/dsound.h"
|
||||
#if defined _WIN32_
|
||||
#include "../Hv_Lib_DirectX90c/dsound.h"
|
||||
#endif
|
||||
#if defined _LINUX_
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <pthread.h> // pthread_create, pthread_mutex_unlock
|
||||
#endif
|
||||
|
||||
#define SC_SIZE_L 128
|
||||
#define CLOSED_TEXT "The sound device is closed."
|
||||
//#include <complex.h> // hv ima na dolu deklaracii / Use native C99 complex type for fftw3
|
||||
#define SAMP_BUFFER_SIZE 80000 //Linux size of arrays used to capture samples
|
||||
#define CLIP32 2147483647
|
||||
#define CLIP16 32767
|
||||
|
||||
#define MAXDSBUFERTIME_W 10 //2.49 =10sec old=7 seconds buffer time
|
||||
#define CHANNELS_W 2 //2 kamala
|
||||
#define BITPERSAMPLE_W 16 // 16bit
|
||||
// (192000 * (( CHANNELS_W * BITPERSAMPLE_W ) / 8)) * MAXDSBUFERTIME_W;
|
||||
#define SAMP_BUFFER_SIZE_WIN ((96000 * (( CHANNELS_W * BITPERSAMPLE_W ) / 8)) * MAXDSBUFERTIME_W + 32) // 5376000 za 192000hz i 7 sec MAXDSBUFERTIME ->vista e vinovna
|
||||
#define SAMP_BUFFER_PRE_BUFF (12000 * 15) //samplerate * seconds
|
||||
|
||||
#define RMS_BUF_SIZE 20 // triabwa da e po goliamo ot max rms_points v TSettingsGeoRad
|
||||
//otide v config.h #define POINTS_IN1_SCAN 620//384 //i v graphdisprad.cpp saved_points_in_1scan = 384;
|
||||
//vazno->POINTS_IN1_SCAN = 384 ot geocore; i time_1scan = 26.81 ot graphdisprad->se glasi to4nostta
|
||||
//vazno->dannite sa ot hardware
|
||||
// kolko to4ki ima w edin skan s prodalzitelnost 8.7ms na 44100HZ sample rate;
|
||||
|
||||
#include <complex.h> // gnu++11 c++11
|
||||
#define complex _Complex
|
||||
|
||||
|
||||
#include "../Hv_Lib_fftw/fftw3.h"
|
||||
|
||||
#include "../HvMsPlayer/libsound/HvRawFilter/hvrawfilter.h" //hv
|
||||
|
||||
//#include "msplayerhv.h"
|
||||
|
||||
/*
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
class ThreadRefr : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void refresh();
|
||||
private:
|
||||
//QMutex m_mutex;
|
||||
void run()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
//QMutexLocker locker(&m_mutex);
|
||||
msleep(5);
|
||||
refresh();
|
||||
//usleep(10);
|
||||
}
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
extern int _GetRxAudioReadTci_();
|
||||
extern void _SetRxAudioTci_(short *,int);
|
||||
|
||||
class MsCore : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MsCore();
|
||||
~MsCore();
|
||||
|
||||
//static void SetTxAudioTci(short *,int);
|
||||
bool is_select_sound_device;
|
||||
bool GetSta_Sto()
|
||||
{
|
||||
return sta_sto_flag;
|
||||
};
|
||||
void SetStr_Sto(bool);
|
||||
void close_sound();
|
||||
void SetupSettings(QString,int,int,int);//QString,
|
||||
void SetMode(int mod_iden);
|
||||
void setVDFftwStartStopFreq(int beg,int end);
|
||||
void SetDecBusy(bool);
|
||||
void SetVDispSpeed(int);
|
||||
//void SetAdleDisplay_VD(bool);
|
||||
|
||||
public slots:
|
||||
void ReciveData(short*, int, bool); //1.27 psk rep fopen bool true false no file open
|
||||
void SetInLevel(int);
|
||||
void FastResetSoundCardIn();
|
||||
//void SetVDispSpeed(int);
|
||||
//void SetDecBusy(bool);
|
||||
|
||||
signals:
|
||||
void Sed_SMeter(int);
|
||||
void Set_Graph(double*,int);
|
||||
void Set_Raw(short*,int,bool); //1.27 psk rep fopen bool true false no file open
|
||||
void Refresh_time();
|
||||
|
||||
private slots:
|
||||
void Refresh_t();
|
||||
void FastResetSoundCardIn_p();
|
||||
|
||||
private:
|
||||
void ResampleAndFilter(short *,int);
|
||||
bool ftci;//tci
|
||||
void ReadTci();//tci
|
||||
bool dec_busy;
|
||||
QTimer *timer_fr_sound;
|
||||
|
||||
int s_data_dsp_height;
|
||||
int s_fft_end_frq;
|
||||
int s_data_width;
|
||||
int s_data_height;
|
||||
int s_fft_cut_low_frq;
|
||||
|
||||
int count_rfesh_sm;
|
||||
short buf_samp_sm[500];
|
||||
|
||||
int s_vdisp_speed;
|
||||
int s_freq_end; //2150hz
|
||||
int s_freq_beg;
|
||||
bool f_disp_v_h;
|
||||
unsigned int last_reset_sc_in;
|
||||
//void FastResetSound();
|
||||
//void setPeriodTime(int);
|
||||
void SetupSettings_(QString,QString,int,int,int,bool);
|
||||
int s_mod_iden;
|
||||
void Get_Graph(int);
|
||||
void record_app();
|
||||
|
||||
bool sta_sto_flag;
|
||||
bool g_read_snd;
|
||||
void decode_fft_size_samples(short*,int);
|
||||
bool draw_flag;
|
||||
|
||||
//double rms_point[RMS_BUF_SIZE];
|
||||
//double sinh_point[RMS_BUF_SIZE];
|
||||
int y_count;
|
||||
int saved_sinh_val;
|
||||
int compare_sinh_val;
|
||||
int sinh_sleep;
|
||||
int koef_sinh_sleep;
|
||||
|
||||
//int save_rms_points;
|
||||
|
||||
enum fft_status
|
||||
{
|
||||
EMPTY, // fft_data is currently unused
|
||||
FILLING, // now writing samples to this fft
|
||||
READY
|
||||
}
|
||||
; // ready to perform fft
|
||||
typedef struct
|
||||
{
|
||||
fftw_complex * samples; // complex data for fft
|
||||
fftw_plan plan_dsp; // fft plan for fftW
|
||||
int index; // position of next fft sample
|
||||
enum fft_status status; // whether the fft is busy
|
||||
}
|
||||
fft_data;
|
||||
|
||||
fft_data * FFT1, * FFT2; // data for two fft's
|
||||
fft_data * ptWriteFft; // Write the current samples to this fft
|
||||
double * fft_avg; // Array to average the FFT
|
||||
double * fft_window; // Window for FFT data
|
||||
int count_fft; // how many fft's have occurred (for average)
|
||||
int fft_size; // size of fft, e.g. 1024
|
||||
|
||||
int average_count; // Number of FFT's to average for graph
|
||||
int fft_error; // fft error count
|
||||
double s_scale;
|
||||
|
||||
int count_ftt_window;
|
||||
short audiobuffer[SAMP_BUFFER_PRE_BUFF];
|
||||
int fftw_sample_rate;
|
||||
int koef_resample;
|
||||
int in_sample_rate;
|
||||
|
||||
struct sound_conf
|
||||
{
|
||||
char dev_capt_name[SC_SIZE_L];
|
||||
char err_msg[SC_SIZE_L];
|
||||
int bad_device;
|
||||
unsigned int rate_min;
|
||||
unsigned int rate_max;
|
||||
unsigned int chan_min;
|
||||
unsigned int chan_max;
|
||||
//int sample_rate;
|
||||
int channel_I;
|
||||
int channel_Q;
|
||||
int data_poll_usec;
|
||||
int latency_millisecs;
|
||||
char msg1[128];
|
||||
int read_error;
|
||||
int write_error;
|
||||
int underrun_error;
|
||||
int interupts;
|
||||
} ;
|
||||
struct sound_conf rad_sound_state;
|
||||
|
||||
short all_data[SAMP_BUFFER_SIZE_WIN];
|
||||
short cSamples_mono[SAMP_BUFFER_SIZE_WIN/2];
|
||||
//double cSamples_r[SAMP_BUFFER_SIZE_WIN/2];
|
||||
|
||||
#if defined _WIN32_
|
||||
bool start_sound();
|
||||
bool stop_sound();
|
||||
bool select_device(bool immediately);//2.49
|
||||
bool ReadData();
|
||||
//bool ReadData_1();
|
||||
DWORD CapturePosition; // capture position in the capture buffer
|
||||
DWORD ReadPosition; // read position in the capture buffer
|
||||
//DWORD PreviousReadPosition;
|
||||
WAVEFORMATEX wf; // .wav format description structure
|
||||
DSCBUFFERDESC dscbd; // DirectSoundCaptureBuffer description structure
|
||||
LPDIRECTSOUNDCAPTURE lpdCapture; // Pointer to IDirectSoundCapture8 object
|
||||
LPDIRECTSOUNDCAPTUREBUFFER lpdCaptureBuff; // Holds DirectSoundCaptureBuffer object
|
||||
DSCBCAPS dscbcaps; // DirectSoundCapture Buffer capabilities
|
||||
#endif
|
||||
#if defined _LINUX_
|
||||
///alsa_sound
|
||||
enum
|
||||
{ // Method of converting sample bytes to an int
|
||||
ThreeLittle2Little, // Three little endian bytes to little endian int
|
||||
ThreeLittle2Big
|
||||
} // Three little endian bytes to big endian int
|
||||
convert_sample_bytes;
|
||||
|
||||
int alsa_read_sound();
|
||||
void open_alsa_capture();
|
||||
snd_pcm_t *hCapture; // handle for alsa soundcard capture or NULL
|
||||
//snd_pcm_t *hPlayback; // handle for alsa soundcard playback
|
||||
snd_pcm_format_t check_formats(snd_pcm_t *h, snd_pcm_hw_params_t *hware);
|
||||
int channel_I;
|
||||
int channel_Q;
|
||||
int chan_capt, chan_play;
|
||||
int latency_frames; // desired latency in audio play samples
|
||||
//int play_buffer_size; // Size of play buffer in samples
|
||||
int sample_bytes; // Size of one channel sample in bytes, either 2 or 4
|
||||
int is_little_endian;
|
||||
void rad_close_sound();
|
||||
void rad_open_sound();
|
||||
int read_alsa();
|
||||
short buffer2[SAMP_BUFFER_SIZE]; // Buffer for 2-byte samples from sound
|
||||
int quisk_overrange; // count of ADC overrange (clip)
|
||||
unsigned char buffer3[3 * SAMP_BUFFER_SIZE]; // Buffer for 3-byte samples from sound
|
||||
int buffer4[SAMP_BUFFER_SIZE]; // Buffer for 4-byte samples from sound
|
||||
int cSamples_l[SAMP_BUFFER_SIZE];
|
||||
int cSamples_r[SAMP_BUFFER_SIZE];
|
||||
|
||||
bool is_pulse_a_in;
|
||||
|
||||
//void loop_read_in();
|
||||
//pthread_mutex_t _e9k8_start_loop;
|
||||
#endif
|
||||
int s_count_resample;
|
||||
|
||||
///int period_time_sec;
|
||||
double s_in_level;
|
||||
|
||||
HvRawFilter *THvRawFilter;
|
||||
/*double raw_1[RAW_BUFFER_SIZE];
|
||||
int raw_1_count;
|
||||
double raw_2[RAW_BUFFER_SIZE];
|
||||
int raw_2_count;*/
|
||||
//int mute_c;
|
||||
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
232
MSHV_269/src/HvMsCore/winsound_in.cpp
Normal file
232
MSHV_269/src/HvMsCore/winsound_in.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
/* MSHV MsCore part of win sound in
|
||||
* Copyright 2015 Hrisimir Hristov, LZ2HV
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
#include "mscore.h"
|
||||
#if defined _WIN32_
|
||||
|
||||
//#include <QtGui>
|
||||
|
||||
QString ConvertToStr_tin(LPCTSTR name)
|
||||
{
|
||||
QString s;
|
||||
for (unsigned int i=0; i<wcslen(name); ++i)
|
||||
s.push_back(name[i]);
|
||||
//s.append(" Микрофон 128 で簡単に作れますが"); //for test coding utf-8
|
||||
return s.toUtf8();
|
||||
}
|
||||
static bool _infirst_ = false;
|
||||
static LPGUID _inguid_;
|
||||
static QString _inname_;//LPCTSTR=lpszDesc LPCTSTR=lpszDrvName=*.dll LPVOID=pContext
|
||||
BOOL CALLBACK DSEnumProc_t_in(LPGUID lpGUID,LPCTSTR lpszDesc,LPCTSTR,LPVOID)
|
||||
{
|
||||
if (!_infirst_)
|
||||
{
|
||||
if (_inname_ == ConvertToStr_tin(lpszDesc))
|
||||
{
|
||||
_infirst_ = true;
|
||||
_inguid_ = lpGUID; //qDebug()<<"Find In="<<_inname_<<_inguid_;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MsCore::ReadData()
|
||||
{
|
||||
// check to see if this is the first time data was requested from buffer
|
||||
if ( ( CapturePosition == (DWORD)-1 ) && ( ReadPosition == (DWORD)-1 ) )
|
||||
{
|
||||
lpdCaptureBuff->GetCurrentPosition( &CapturePosition, &ReadPosition );
|
||||
//PreviousReadPosition = ReadPosition;
|
||||
//qDebug()<<"FIRST RESET lpdCaptureBuff->GetCurrentPosition"<<CapturePosition<<ReadPosition;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get former read and capture positions and acquire new ones
|
||||
//DWORD PreviousCapturePosition;
|
||||
//PreviousCapturePosition = CapturePosition;
|
||||
DWORD PreviousReadPosition = ReadPosition;
|
||||
//DWORD temp_PreviousReadPosition = ReadPosition;
|
||||
//PreviousReadPosition = ReadPosition;
|
||||
|
||||
//if( FAILED( hr = g_pDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) )
|
||||
// return hr;
|
||||
if ( FAILED(lpdCaptureBuff->GetCurrentPosition( &CapturePosition, &ReadPosition ) ) )
|
||||
{
|
||||
//qDebug()<<"********* FAILED lpdCaptureBuff->GetCurrentPosition";
|
||||
//ReadPosition = temp_PreviousReadPosition;
|
||||
return false;
|
||||
}
|
||||
//lpdCaptureBuff->GetCurrentPosition( &CapturePosition, &ReadPosition );
|
||||
|
||||
LPVOID CBAddress1, CBAddress2;
|
||||
DWORD CBLength1, CBLength2;
|
||||
DWORD LockSize;
|
||||
|
||||
if ( ReadPosition < PreviousReadPosition )
|
||||
LockSize = ( dscbd.dwBufferBytes - PreviousReadPosition ) + ReadPosition;
|
||||
else
|
||||
LockSize = ReadPosition - PreviousReadPosition;
|
||||
|
||||
if ( LockSize != 0 )
|
||||
{
|
||||
|
||||
if ( FAILED( lpdCaptureBuff->Lock(
|
||||
PreviousReadPosition, // Offset at which to start lock.
|
||||
LockSize, // Size of lock.
|
||||
&CBAddress1, // Gets address of first part of lock.
|
||||
&CBLength1, // Gets size of first part of lock.
|
||||
&CBAddress2, // Address of wraparound.
|
||||
&CBLength2, // Size of wraparound.
|
||||
0 ) ) ) // Flag.
|
||||
return false;
|
||||
|
||||
memcpy((char*)all_data,CBAddress1,CBLength1);//2.56 (char*)
|
||||
|
||||
if (CBAddress2) // if new data wraps around the capture buffer
|
||||
memcpy(((char*)all_data + CBLength1),CBAddress2,CBLength2);//2.56 (char*)
|
||||
|
||||
//if( CBAddress2 )
|
||||
//qDebug()<<"1Lock, CBLength1, CBLength2"<<LockSize<<CBLength1<<CBLength2<<CBLength1+CBLength2;
|
||||
//if ( CBAddress2 != NULL )
|
||||
//qDebug()<<"2Lock, CBLength1, CBLength2"<<LockSize<<CBLength1<<CBLength2<<CBLength1+CBLength2;
|
||||
|
||||
if (LockSize <= 0) return false;
|
||||
|
||||
int count = 0; //qDebug()<<LockSize;
|
||||
for (int i = 0; i < (int)LockSize/2; i+=2)
|
||||
{
|
||||
//double data_l = THvRawFilter->band_l((double)all_data[i+rad_sound_state.channel_I]);
|
||||
//cSamples_mono[count] = (short int)data_l;
|
||||
cSamples_mono[count] = all_data[i+rad_sound_state.channel_I];
|
||||
count++;
|
||||
}
|
||||
|
||||
ResampleAndFilter(cSamples_mono,count); //2.57
|
||||
/*short *dat_tt = new short[count+6];
|
||||
int k = 0;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if (s_count_resample==koef_resample)
|
||||
{
|
||||
double data_l = THvRawFilter->band_l((double)cSamples_mono[i]);
|
||||
dat_tt[k]=(short int)(data_l*s_in_level);
|
||||
s_count_resample = 0;
|
||||
k++;
|
||||
}
|
||||
else
|
||||
s_count_resample++;
|
||||
}
|
||||
ReciveData(dat_tt,k,false); //1.27 psk rep fopen bool true false no file open
|
||||
delete [] dat_tt;*/
|
||||
|
||||
if ( FAILED( lpdCaptureBuff->Unlock(
|
||||
CBAddress1, // Gets address of first part of lock.
|
||||
CBLength1, // Gets size of first part of lock.
|
||||
CBAddress2, // Address of wraparound not needed.
|
||||
CBLength2 ) ) ) // Size of wraparound not needed.
|
||||
return false;
|
||||
//ReciveData(dat_tt,k,false);
|
||||
//delete dat_tt;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MsCore::stop_sound()
|
||||
{
|
||||
if (FAILED(lpdCaptureBuff->Stop()))
|
||||
return false;
|
||||
|
||||
CapturePosition = (DWORD)-1; // reset capture position
|
||||
ReadPosition = (DWORD)-1; // reset read position
|
||||
//PreviousReadPosition = (DWORD)-1;
|
||||
return true;
|
||||
}
|
||||
bool MsCore::start_sound()
|
||||
{
|
||||
if (FAILED(lpdCaptureBuff->Start(DSCBSTART_LOOPING)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool MsCore::select_device(bool immediately)
|
||||
{
|
||||
///return false; //for test error
|
||||
//qDebug() << "--------------------------------";
|
||||
|
||||
static LPGUID prev_inguid = (LPGUID)-1;//2.50 protect at start no primary sound driver =(-1)
|
||||
DWORD pv; // Can be any 32-bit type.
|
||||
_infirst_ = false;
|
||||
_inguid_ = (LPGUID)0;
|
||||
_inname_ = (QString)rad_sound_state.dev_capt_name;
|
||||
if ( DS_OK != DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)DSEnumProc_t_in, (VOID*)&pv))
|
||||
{
|
||||
//qDebug()<<"EROR DirectSoundCaptureEnumerate";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!immediately)
|
||||
{
|
||||
if (prev_inguid != _inguid_) //2.49 exception GUID is Changed
|
||||
{
|
||||
//g_read_snd = false;//true;
|
||||
close_sound(); //qDebug()<<"GUID Changed Close---->";
|
||||
usleep(2000);
|
||||
//g_read_snd = true;//false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//qDebug()<<"GUID No Changed Return";
|
||||
return true;
|
||||
}
|
||||
} //else qDebug()<<"RESET immediately";
|
||||
//prev_inguid = _inguid_;//2.50 stop
|
||||
|
||||
CapturePosition = (DWORD)-1; // reset capture position
|
||||
ReadPosition = (DWORD)-1; // reset read position
|
||||
|
||||
// Set up wave format structure.
|
||||
ZeroMemory( &wf, sizeof( wf ) );
|
||||
wf.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wf.nChannels = CHANNELS_W;
|
||||
wf.wBitsPerSample = BITPERSAMPLE_W;
|
||||
wf.nSamplesPerSec = in_sample_rate;//rad_sound_state.sample_rate;
|
||||
wf.nBlockAlign = ( wf.nChannels * wf.wBitsPerSample ) / 8; // ( nChannels * wBitsPerSample ) / 8 bits per byte
|
||||
wf.nAvgBytesPerSec = ( wf.nSamplesPerSec * wf.nBlockAlign );
|
||||
//qDebug() << "wf.nAvgBytesPerSec"<<wf.nAvgBytesPerSec;
|
||||
|
||||
// Set up DSBUFFERDESC structure: Buffer Control Options
|
||||
ZeroMemory(&dscbd, sizeof( dscbd ) );
|
||||
dscbd.dwSize = sizeof( DSCBUFFERDESC );
|
||||
dscbd.dwFlags = 0;
|
||||
dscbd.dwBufferBytes = wf.nAvgBytesPerSec * MAXDSBUFERTIME_W; //max->3840000 buffer for 192000 ->5 second buffer
|
||||
dscbd.dwReserved = 0;
|
||||
dscbd.lpwfxFormat = &wf;
|
||||
dscbd.dwFXCount = 0;
|
||||
dscbd.lpDSCFXDesc = NULL;
|
||||
//qDebug() << "dscbd.dwBufferBytes"<<dscbd.dwBufferBytes;
|
||||
|
||||
lpdCapture = NULL;
|
||||
if (FAILED( DirectSoundCaptureCreate(_inguid_,&lpdCapture,NULL)))
|
||||
{
|
||||
//qDebug()<<"EROR DirectSoundCaptureCreate"; // insert error handling
|
||||
return false;
|
||||
}
|
||||
|
||||
lpdCaptureBuff = NULL;
|
||||
if (FAILED(lpdCapture->CreateCaptureBuffer(&dscbd,&lpdCaptureBuff,NULL)))
|
||||
{
|
||||
//qDebug()<<"EROR CreateCaptureBuffer"; //here is problem if not any device ON
|
||||
return false;
|
||||
}
|
||||
prev_inguid = _inguid_;//2.50 need to be here if setup is ok save->prev_inguid
|
||||
|
||||
// Set up DSBCAPS structure: Buffer Capabilities
|
||||
ZeroMemory( &dscbcaps, sizeof( dscbcaps ) );
|
||||
dscbcaps.dwSize = sizeof( DSCBCAPS );
|
||||
|
||||
// Find the maximum playback offset position
|
||||
lpdCaptureBuff->GetCaps( &dscbcaps );
|
||||
//qDebug()<<dscbcaps.dwBufferBytes;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user