X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Foutput%2Fwav.c;h=f991cbfdc68526d9fea8754ad200565b712076a9;hb=e5ff8e9e0a12d54963814debeab50cd88ecca632;hp=8aa787bd3f14e36f67fc7a58e870b20c98762fc2;hpb=364859ac732fadddada2d1622dfec7f2ba2fef76;p=libsigrok.git diff --git a/src/output/wav.c b/src/output/wav.c index 8aa787bd..f991cbfd 100644 --- a/src/output/wav.c +++ b/src/output/wav.c @@ -17,8 +17,9 @@ * along with this program. If not, see . */ +#include #include -#include "libsigrok.h" +#include #include "libsigrok-internal.h" #define LOG_PREFIX "output/wav" @@ -27,6 +28,7 @@ #define MIN_DATA_CHUNK_SAMPLES 10 struct out_context { + double scale; gboolean header_done; uint64_t samplerate; int num_channels; @@ -34,6 +36,7 @@ struct out_context { int chanbuf_size; int *chanbuf_used; uint8_t **chanbuf; + float *fdata; }; static int realloc_chanbufs(const struct sr_output *o, int size) @@ -91,10 +94,9 @@ static int init(struct sr_output *o, GHashTable *options) struct sr_channel *ch; GSList *l; - (void)options; - outc = g_malloc0(sizeof(struct out_context)); o->priv = outc; + outc->scale = g_variant_get_double(g_hash_table_lookup(options, "scale")); for (l = o->sdi->channels; l; l = l->next) { ch = l->data; @@ -229,16 +231,21 @@ static int check_chanbuf_size(const struct sr_output *o) return size; } + static int receive(const struct sr_output *o, const struct sr_datafeed_packet *packet, GString **out) { struct out_context *outc; const struct sr_datafeed_meta *meta; + const struct sr_datafeed_analog_old *analog_old; const struct sr_datafeed_analog *analog; const struct sr_config *src; struct sr_channel *ch; GSList *l; - int num_channels, size, *chan_idx, idx, i, j; + const GSList *channels; + float f; + int num_channels, num_samples, size, *chan_idx, idx, i, j, ret; + float *data; uint8_t *buf; *out = NULL; @@ -255,6 +262,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p outc->samplerate = g_variant_get_uint64(src->data); } break; + case SR_DF_ANALOG_OLD: case SR_DF_ANALOG: if (!outc->header_done) { *out = gen_header(o); @@ -262,34 +270,55 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p } else *out = g_string_sized_new(512); + analog_old = packet->payload; analog = packet->payload; - if (analog->num_samples == 0) + + if (packet->type == SR_DF_ANALOG_OLD) { + num_samples = analog_old->num_samples; + channels = analog_old->channels; + num_channels = g_slist_length(analog_old->channels); + data = analog_old->data; + } else { + num_samples = analog->num_samples; + channels = analog->meaning->channels; + num_channels = g_slist_length(analog->meaning->channels); + if (!(data = g_try_realloc(outc->fdata, sizeof(float) * num_samples * num_channels))) + return SR_ERR_MALLOC; + outc->fdata = data; + ret = sr_analog_to_float(analog, data); + if (ret != SR_OK) + return ret; + } + + if (num_samples == 0) return SR_OK; - num_channels = g_slist_length(analog->channels); if (num_channels > outc->num_channels) { sr_err("Packet has %d channels, but only %d were enabled.", num_channels, outc->num_channels); return SR_ERR; } - if (analog->num_samples > outc->chanbuf_size) { - if (realloc_chanbufs(o, analog->num_samples) != SR_OK) + if (num_samples > outc->chanbuf_size) { + if (realloc_chanbufs(o, analog_old->num_samples) != SR_OK) return SR_ERR_MALLOC; } /* Index the channels in this packet, so we can interleave quicker. */ chan_idx = g_malloc(sizeof(int) * outc->num_channels); for (i = 0; i < num_channels; i++) { - ch = g_slist_nth_data(analog->channels, i); + ch = g_slist_nth_data((GSList *) channels, i); chan_idx[i] = g_slist_index(outc->channels, ch); } - for (i = 0; i < analog->num_samples; i++) { + for (i = 0; i < num_samples; i++) { for (j = 0; j < num_channels; j++) { idx = chan_idx[j]; buf = outc->chanbuf[idx] + outc->chanbuf_used[idx]++ * 4; - float_to_le(buf, analog->data[i * num_channels + j]); + f = data[i * num_channels + j]; + if (outc->scale != 0.0) + f /= outc->scale; + float_to_le(buf, f); } } g_free(chan_idx); @@ -312,6 +341,19 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p return SR_OK; } +static struct sr_option options[] = { + { "scale", "Scale", "Scale values by factor", NULL, NULL }, + ALL_ZERO +}; + +static const struct sr_option *get_options(void) +{ + if (!options[0].def) + options[0].def = g_variant_ref_sink(g_variant_new_double(0.0)); + + return options; +} + static int cleanup(struct sr_output *o) { struct out_context *outc; @@ -319,10 +361,12 @@ static int cleanup(struct sr_output *o) outc = o->priv; g_slist_free(outc->channels); + g_variant_unref(options[0].def); for (i = 0; i < outc->num_channels; i++) g_free(outc->chanbuf[i]); g_free(outc->chanbuf_used); g_free(outc->chanbuf); + g_free(outc->fdata); g_free(outc); o->priv = NULL; @@ -332,9 +376,11 @@ static int cleanup(struct sr_output *o) SR_PRIV struct sr_output_module output_wav = { .id = "wav", .name = "WAV", - .desc = "WAVE file format", + .desc = "Microsoft WAV file format", + .exts = (const char*[]){"wav", NULL}, + .flags = 0, + .options = get_options, .init = init, .receive = receive, .cleanup = cleanup, }; -