* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdint.h>
-#include "libsigrok.h"
+#include <libsigrok/libsigrok.h>
#include "libsigrok-internal.h"
#define LOG_PREFIX "input/wav"
#define MIN_DATA_CHUNK_OFFSET 45
/* Expect to find the "data" chunk within this offset from the start. */
-#define MAX_DATA_CHUNK_OFFSET 256
+#define MAX_DATA_CHUNK_OFFSET 1024
-#define WAVE_FORMAT_PCM 0x0001
-#define WAVE_FORMAT_IEEE_FLOAT 0x0003
-#define WAVE_FORMAT_EXTENSIBLE 0xfffe
+#define WAVE_FORMAT_PCM_ 0x0001
+#define WAVE_FORMAT_IEEE_FLOAT_ 0x0003
+#define WAVE_FORMAT_EXTENSIBLE_ 0xfffe
struct context {
gboolean started;
return SR_ERR_DATA;
}
- if (fmt_code == WAVE_FORMAT_PCM) {
- } else if (fmt_code == WAVE_FORMAT_IEEE_FLOAT) {
+ if (fmt_code == WAVE_FORMAT_PCM_) {
+ } else if (fmt_code == WAVE_FORMAT_IEEE_FLOAT_) {
if (unitsize != 4) {
sr_err("only 32-bit floats supported.");
return SR_ERR_DATA;
}
- } else if (fmt_code == WAVE_FORMAT_EXTENSIBLE) {
+ } else if (fmt_code == WAVE_FORMAT_EXTENSIBLE_) {
if (buf->len < 70)
/* Not enough for extensible header and next chunk. */
return SR_ERR_NA;
}
/* Real format code is the first two bytes of the GUID. */
fmt_code = RL16(buf->str + 44);
- if (fmt_code != WAVE_FORMAT_PCM && fmt_code != WAVE_FORMAT_IEEE_FLOAT) {
+ if (fmt_code != WAVE_FORMAT_PCM_ && fmt_code != WAVE_FORMAT_IEEE_FLOAT_) {
sr_err("Only PCM and floating point samples are supported.");
return SR_ERR_DATA;
}
- if (fmt_code == WAVE_FORMAT_IEEE_FLOAT && unitsize != 4) {
+ if (fmt_code == WAVE_FORMAT_IEEE_FLOAT_ && unitsize != 4) {
sr_err("only 32-bit floats supported.");
return SR_ERR_DATA;
}
/* Skip into the samples. */
return offset + 8;
for (i = 0; i < 4; i++) {
- if (!isalpha(buf->str[offset + i])
- && !isascii(buf->str[offset + i])
+ if (!isalnum(buf->str[offset + i])
&& !isblank(buf->str[offset + i]))
/* Doesn't look like a chunk ID. */
return -1;
offset += 8 + RL32(buf->str + offset + 4);
}
+ if (offset > MAX_DATA_CHUNK_OFFSET)
+ return -1;
+
return offset;
}
{
struct sr_datafeed_packet packet;
struct sr_datafeed_analog analog;
+ struct sr_analog_encoding encoding;
+ struct sr_analog_meaning meaning;
+ struct sr_analog_spec spec;
struct context *inc;
float fdata[CHUNK_SIZE];
- uint64_t sample;
int total_samples, samplenum;
char *s, *d;
memset(fdata, 0, CHUNK_SIZE);
total_samples = num_samples * inc->num_channels;
for (samplenum = 0; samplenum < total_samples; samplenum++) {
- if (inc->fmt_code == WAVE_FORMAT_PCM) {
- sample = 0;
- memcpy(&sample, s, inc->unitsize);
- switch (inc->samplesize) {
+ if (inc->fmt_code == WAVE_FORMAT_PCM_) {
+ switch (inc->unitsize) {
case 1:
/* 8-bit PCM samples are unsigned. */
- fdata[samplenum] = (uint8_t)sample / (float)255;
+ fdata[samplenum] = *(uint8_t*)(s) / (float)255;
break;
case 2:
- fdata[samplenum] = RL16S(&sample) / (float)INT16_MAX;
+ fdata[samplenum] = RL16S(s) / (float)INT16_MAX;
break;
case 4:
- fdata[samplenum] = RL32S(&sample) / (float)INT32_MAX;
+ fdata[samplenum] = RL32S(s) / (float)INT32_MAX;
break;
}
} else {
s += inc->unitsize;
d += inc->unitsize;
}
+
+ sr_analog_init(&analog, &encoding, &meaning, &spec, 0);
packet.type = SR_DF_ANALOG;
packet.payload = &analog;
- analog.channels = in->sdi->channels;
analog.num_samples = num_samples;
- analog.mq = 0;
- analog.mqflags = 0;
- analog.unit = 0;
analog.data = fdata;
+ analog.meaning->channels = in->sdi->channels;
+ analog.meaning->mq = 0;
+ analog.meaning->mqflags = 0;
+ analog.meaning->unit = 0;
sr_session_send(in->sdi, &packet);
}
struct sr_config *src;
int offset, chunk_samples, total_samples, processed, max_chunk_samples;
int num_samples, i;
- char channelname[8];
inc = in->priv;
if (!inc->started) {
- for (i = 0; i < inc->num_channels; i++) {
- snprintf(channelname, 8, "CH%d", i + 1);
- sr_channel_new(in->sdi, i, SR_CHANNEL_ANALOG, TRUE, channelname);
- }
-
- std_session_send_df_header(in->sdi, LOG_PREFIX);
+ std_session_send_df_header(in->sdi);
packet.type = SR_DF_META;
packet.payload = &meta;
src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(inc->samplerate));
meta.config = g_slist_append(NULL, src);
sr_session_send(in->sdi, &packet);
+ g_slist_free(meta.config);
sr_config_free(src);
inc->started = TRUE;
offset = 0;
/* Round off up to the last channels * unitsize boundary. */
- chunk_samples = (in->buf->len - offset) / inc->num_channels / inc->unitsize;
- max_chunk_samples = CHUNK_SIZE / inc->num_channels / inc->unitsize;
+ chunk_samples = (in->buf->len - offset) / inc->samplesize;
+ max_chunk_samples = CHUNK_SIZE / inc->samplesize;
processed = 0;
total_samples = chunk_samples;
while (processed < total_samples) {
else
num_samples = chunk_samples;
send_chunk(in, offset, num_samples);
- offset += num_samples * inc->unitsize;
+ offset += num_samples * inc->samplesize;
chunk_samples -= num_samples;
processed += num_samples;
}
{
struct context *inc;
int ret;
+ char channelname[8];
g_string_append_len(in->buf, buf->str, buf->len);
else if (ret != SR_OK)
return ret;
+ for (int i = 0; i < inc->num_channels; i++) {
+ snprintf(channelname, 8, "CH%d", i + 1);
+ sr_channel_new(in->sdi, i, SR_CHANNEL_ANALOG, TRUE, channelname);
+ }
+
/* sdi is ready, notify frontend. */
in->sdi_ready = TRUE;
return SR_OK;
static int end(struct sr_input *in)
{
- struct sr_datafeed_packet packet;
struct context *inc;
int ret;
ret = SR_OK;
inc = in->priv;
- if (inc->started) {
- packet.type = SR_DF_END;
- sr_session_send(in->sdi, &packet);
- }
+ if (inc->started)
+ std_session_send_df_end(in->sdi);
return ret;
}
+static int reset(struct sr_input *in)
+{
+ struct context *inc = in->priv;
+
+ inc->started = FALSE;
+ g_string_truncate(in->buf, 0);
+
+ return SR_OK;
+}
+
SR_PRIV struct sr_input_module input_wav = {
.id = "wav",
.name = "WAV",
.init = init,
.receive = receive,
.end = end,
+ .reset = reset,
};