mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	audioconvert: add debug.wav-path to save wav
This commit is contained in:
		
							parent
							
								
									7b13f6d26b
								
							
						
					
					
						commit
						0563e1da52
					
				
					 4 changed files with 341 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -29,6 +29,7 @@
 | 
			
		|||
#include "fmt-ops.h"
 | 
			
		||||
#include "channelmix-ops.h"
 | 
			
		||||
#include "resample.h"
 | 
			
		||||
#include "wavfile.h"
 | 
			
		||||
 | 
			
		||||
#undef SPA_LOG_TOPIC_DEFAULT
 | 
			
		||||
#define SPA_LOG_TOPIC_DEFAULT log_topic
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +73,7 @@ struct props {
 | 
			
		|||
	unsigned int resample_disabled:1;
 | 
			
		||||
	unsigned int resample_quality;
 | 
			
		||||
	double rate;
 | 
			
		||||
	char wav_path[512];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void props_reset(struct props *props)
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +91,7 @@ static void props_reset(struct props *props)
 | 
			
		|||
	props->resample_disabled = false;
 | 
			
		||||
	props->resample_quality = RESAMPLE_DEFAULT_QUALITY;
 | 
			
		||||
	props->rate = 1.0;
 | 
			
		||||
	spa_zero(props->wav_path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct buffer {
 | 
			
		||||
| 
						 | 
				
			
			@ -207,6 +210,8 @@ struct impl {
 | 
			
		|||
	float *scratch;
 | 
			
		||||
	float *tmp[2];
 | 
			
		||||
	float *tmp_datas[2][MAX_PORTS];
 | 
			
		||||
 | 
			
		||||
	struct wav_file *wav_file;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CHECK_PORT(this,d,p)		((p) < this->dir[d].n_ports)
 | 
			
		||||
| 
						 | 
				
			
			@ -637,6 +642,14 @@ static int impl_node_enum_params(void *object, int seq,
 | 
			
		|||
			spa_pod_builder_pop(&b, &f[1]);
 | 
			
		||||
			param = spa_pod_builder_pop(&b, &f[0]);
 | 
			
		||||
			break;
 | 
			
		||||
		case 24:
 | 
			
		||||
			param = spa_pod_builder_add_object(&b,
 | 
			
		||||
				SPA_TYPE_OBJECT_PropInfo, id,
 | 
			
		||||
				SPA_PROP_INFO_name, SPA_POD_String("debug.wav-path"),
 | 
			
		||||
				SPA_PROP_INFO_description, SPA_POD_String("Path to WAV file"),
 | 
			
		||||
				SPA_PROP_INFO_type, SPA_POD_String(p->wav_path),
 | 
			
		||||
				SPA_PROP_INFO_params, SPA_POD_Bool(true));
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -709,6 +722,8 @@ static int impl_node_enum_params(void *object, int seq,
 | 
			
		|||
			spa_pod_builder_int(&b, this->dir[1].conv.noise_bits);
 | 
			
		||||
			spa_pod_builder_string(&b, "dither.method");
 | 
			
		||||
			spa_pod_builder_string(&b, dither_method_info[this->dir[1].conv.method].label);
 | 
			
		||||
			spa_pod_builder_string(&b, "debug.wav-path");
 | 
			
		||||
			spa_pod_builder_string(&b, p->wav_path);
 | 
			
		||||
			spa_pod_builder_pop(&b, &f[1]);
 | 
			
		||||
			param = spa_pod_builder_pop(&b, &f[0]);
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -782,6 +797,10 @@ static int audioconvert_set_param(struct impl *this, const char *k, const char *
 | 
			
		|||
		spa_atou32(s, &this->dir[1].conv.noise_bits, 0);
 | 
			
		||||
	else if (spa_streq(k, "dither.method"))
 | 
			
		||||
		this->dir[1].conv.method = dither_method_from_label(s);
 | 
			
		||||
	else if (spa_streq(k, "debug.wav-path")) {
 | 
			
		||||
		spa_scnprintf(this->props.wav_path,
 | 
			
		||||
				sizeof(this->props.wav_path), "%s", s ? s : "");
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -2140,6 +2159,30 @@ static int impl_node_port_reuse_buffer(void *object, uint32_t port_id, uint32_t
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_wav(struct impl *this, void **src, uint32_t n_samples)
 | 
			
		||||
{
 | 
			
		||||
	if (SPA_UNLIKELY(this->props.wav_path[0])) {
 | 
			
		||||
		if (this->wav_file == NULL) {
 | 
			
		||||
			struct wav_file_info info;
 | 
			
		||||
 | 
			
		||||
			info.info = this->dir[this->direction].format;
 | 
			
		||||
 | 
			
		||||
			this->wav_file = wav_file_open(this->props.wav_path,
 | 
			
		||||
					"w", &info);
 | 
			
		||||
			if (this->wav_file == NULL)
 | 
			
		||||
				spa_log_warn(this->log, "can't open wav path: %m");
 | 
			
		||||
		}
 | 
			
		||||
		if (this->wav_file) {
 | 
			
		||||
			wav_file_write(this->wav_file, src, n_samples);
 | 
			
		||||
		} else {
 | 
			
		||||
			spa_zero(this->props.wav_path);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (this->wav_file != NULL) {
 | 
			
		||||
		wav_file_close(this->wav_file);
 | 
			
		||||
		this->wav_file = NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int channelmix_process_control(struct impl *this, struct port *ctrlport,
 | 
			
		||||
				      void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
 | 
			
		||||
				      uint32_t n_samples)
 | 
			
		||||
| 
						 | 
				
			
			@ -2532,6 +2575,9 @@ static int impl_node_process(void *object)
 | 
			
		|||
		dst_remap = (void **)dst_datas;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (this->direction == SPA_DIRECTION_INPUT)
 | 
			
		||||
		handle_wav(this, (void**)src_datas, n_samples);
 | 
			
		||||
 | 
			
		||||
	dir = &this->dir[SPA_DIRECTION_INPUT];
 | 
			
		||||
	if (!in_passthrough) {
 | 
			
		||||
		if (mix_passthrough && resample_passthrough && out_passthrough)
 | 
			
		||||
| 
						 | 
				
			
			@ -2619,6 +2665,8 @@ static int impl_node_process(void *object)
 | 
			
		|||
		spa_log_trace_fp(this->log, "%p: output convert %d", this, n_samples);
 | 
			
		||||
		convert_process(&dir->conv, dst_datas, in_datas, n_samples);
 | 
			
		||||
	}
 | 
			
		||||
	if (this->direction == SPA_DIRECTION_OUTPUT)
 | 
			
		||||
		handle_wav(this, dst_datas, n_samples);
 | 
			
		||||
 | 
			
		||||
	spa_log_trace_fp(this->log, "%d/%d  %d/%d %d->%d", this->in_offset, max_in,
 | 
			
		||||
			this->out_offset, max_out, n_samples, n_out);
 | 
			
		||||
| 
						 | 
				
			
			@ -2752,7 +2800,8 @@ static int impl_clear(struct spa_handle *handle)
 | 
			
		|||
		convert_free(&this->dir[0].conv);
 | 
			
		||||
	if (this->dir[1].conv.free)
 | 
			
		||||
		convert_free(&this->dir[1].conv);
 | 
			
		||||
 | 
			
		||||
	if (this->wav_file != NULL)
 | 
			
		||||
		wav_file_close(this->wav_file);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
audioconvert_sources = [
 | 
			
		||||
  'audioadapter.c',
 | 
			
		||||
  'audioconvert.c',
 | 
			
		||||
  'wavfile.c',
 | 
			
		||||
  'plugin.c'
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										249
									
								
								spa/plugins/audioconvert/wavfile.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								spa/plugins/audioconvert/wavfile.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,249 @@
 | 
			
		|||
/* PipeWire
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright © 2022 Wim Taymans
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
 * copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
 * to deal in the Software without restriction, including without limitation
 | 
			
		||||
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
 * Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice (including the next
 | 
			
		||||
 * paragraph) shall be included in all copies or substantial portions of the
 | 
			
		||||
 * Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
			
		||||
 * DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#include <spa/utils/string.h>
 | 
			
		||||
 | 
			
		||||
#include "wavfile.h"
 | 
			
		||||
 | 
			
		||||
#define BLOCK_SIZE	4096
 | 
			
		||||
 | 
			
		||||
struct wav_file {
 | 
			
		||||
	struct spa_audio_info info;
 | 
			
		||||
	int fd;
 | 
			
		||||
	const struct format_info *fi;
 | 
			
		||||
 | 
			
		||||
	uint32_t length;
 | 
			
		||||
 | 
			
		||||
	uint32_t stride;
 | 
			
		||||
	uint32_t blocks;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline ssize_t write_data(struct wav_file *wf, const void *data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t len;
 | 
			
		||||
	len = write(wf->fd, data, size);
 | 
			
		||||
	if (len > 0)
 | 
			
		||||
		wf->length += len;
 | 
			
		||||
	return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t writei(struct wav_file *wf, void **data, size_t samples)
 | 
			
		||||
{
 | 
			
		||||
	return write_data(wf, data[0], samples * wf->stride);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint8_t v[3];
 | 
			
		||||
} __attribute__ ((packed)) uint24_t;
 | 
			
		||||
 | 
			
		||||
#define MAKE_WRITEN_FUNC(name, type)						\
 | 
			
		||||
static ssize_t name (struct wav_file *wf, void **data, size_t samples)	\
 | 
			
		||||
{										\
 | 
			
		||||
	uint32_t b, n, k, blocks = wf->blocks, chunk;				\
 | 
			
		||||
	uint8_t buf[BLOCK_SIZE];						\
 | 
			
		||||
	ssize_t res = 0;							\
 | 
			
		||||
	type **d = (type**)data;						\
 | 
			
		||||
	uint32_t chunk_size = sizeof(buf) / (blocks * sizeof(type));		\
 | 
			
		||||
	for (n = 0; n < samples; ) {						\
 | 
			
		||||
		type *p = (type*)buf;						\
 | 
			
		||||
		chunk = SPA_MIN(samples - n, chunk_size);			\
 | 
			
		||||
		for (k = 0; k < chunk; k++, n++) {				\
 | 
			
		||||
			for (b = 0; b < blocks; b++)				\
 | 
			
		||||
				*p++ = d[b][n];					\
 | 
			
		||||
		}								\
 | 
			
		||||
		res += write_data(wf, buf,					\
 | 
			
		||||
				chunk * blocks * sizeof(type));			\
 | 
			
		||||
	}									\
 | 
			
		||||
	return res;								\
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MAKE_WRITEN_FUNC(writen_8, uint8_t);
 | 
			
		||||
MAKE_WRITEN_FUNC(writen_16, uint16_t);
 | 
			
		||||
MAKE_WRITEN_FUNC(writen_24, uint24_t);
 | 
			
		||||
MAKE_WRITEN_FUNC(writen_32, uint32_t);
 | 
			
		||||
MAKE_WRITEN_FUNC(writen_64, uint64_t);
 | 
			
		||||
 | 
			
		||||
static inline int write_n(int fd, const void *buf, int count)
 | 
			
		||||
{
 | 
			
		||||
	return write(fd, buf, count) == (ssize_t)count ? count : -errno;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int write_le16(int fd, uint16_t val)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t buf[2] = { val, val >> 8 };
 | 
			
		||||
	return write_n(fd, buf, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int write_le32(int fd, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t buf[4] = { val, val >> 8, val >> 16, val >> 24 };
 | 
			
		||||
	return write_n(fd, buf, 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MAKE_AUDIO_RAW(format,bits,planar,fmt,...) \
 | 
			
		||||
	{ SPA_MEDIA_TYPE_audio, SPA_MEDIA_SUBTYPE_raw, format, bits, planar, fmt, __VA_ARGS__ }
 | 
			
		||||
 | 
			
		||||
static struct format_info {
 | 
			
		||||
	uint32_t media_type;
 | 
			
		||||
	uint32_t media_subtype;
 | 
			
		||||
	uint32_t format;
 | 
			
		||||
	uint32_t bits;
 | 
			
		||||
	bool planar;
 | 
			
		||||
	uint32_t fmt;
 | 
			
		||||
	ssize_t (*write) (struct wav_file *wf, void **data, size_t samples);
 | 
			
		||||
} format_info[] = {
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_U8P,		 8, true, 1, writen_8),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_U8,		 8, false, 1, writei),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S16P,		16, true, 1, writen_16),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S16_LE,		16, false, 1, writei),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S24P,		24, true, 1, writen_24),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S24_LE,		24, false, 1, writei),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S24_32P,	32, true, 1, writen_32),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S32P,		32, true, 1, writen_32),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S24_32_LE,	32, false, 1, writei),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_S32_LE,		32, false, 1, writei),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F32P,		32, true, 3, writen_32),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F32_LE,		32, false, 3, writei),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F64P,		64, true, 3, writen_64),
 | 
			
		||||
	MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F64_LE,		32, false, 3, writei),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CHECK_RES(expr) if ((res = (expr)) < 0) return res
 | 
			
		||||
 | 
			
		||||
static int write_headers(struct wav_file *wf)
 | 
			
		||||
{
 | 
			
		||||
	int res;
 | 
			
		||||
	uint32_t channels, rate, bps, bits;
 | 
			
		||||
	const struct format_info *fi = wf->fi;
 | 
			
		||||
 | 
			
		||||
	lseek(wf->fd, 0, SEEK_SET);
 | 
			
		||||
 | 
			
		||||
	rate = wf->info.info.raw.rate;
 | 
			
		||||
	channels = wf->info.info.raw.channels;
 | 
			
		||||
	bits = fi->bits;
 | 
			
		||||
	bps = channels * bits / 8;
 | 
			
		||||
 | 
			
		||||
	CHECK_RES(write_n(wf->fd, "RIFF", 4));
 | 
			
		||||
	CHECK_RES(write_le32(wf->fd, wf->length == 0 ? (uint32_t)-1 : wf->length + 12 + 8 + 16));
 | 
			
		||||
	CHECK_RES(write_n(wf->fd, "WAVE", 4));
 | 
			
		||||
	CHECK_RES(write_n(wf->fd, "fmt ", 4));
 | 
			
		||||
	CHECK_RES(write_le32(wf->fd, 16));
 | 
			
		||||
	CHECK_RES(write_le16(wf->fd, fi->fmt));			/* format */
 | 
			
		||||
	CHECK_RES(write_le16(wf->fd, channels));		/* channels */
 | 
			
		||||
	CHECK_RES(write_le32(wf->fd, rate));			/* rate */
 | 
			
		||||
	CHECK_RES(write_le32(wf->fd, bps * rate));		/* bytes per sec */
 | 
			
		||||
	CHECK_RES(write_le16(wf->fd, bps));			/* bytes per samples */
 | 
			
		||||
	CHECK_RES(write_le16(wf->fd, bits));			/* bits per sample */
 | 
			
		||||
	CHECK_RES(write_n(wf->fd, "data", 4));
 | 
			
		||||
	CHECK_RES(write_le32(wf->fd, wf->length == 0 ? (uint32_t)-1 : wf->length));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct format_info *find_info(struct wav_file_info *info)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t i;
 | 
			
		||||
 | 
			
		||||
	if (info->info.media_type != SPA_MEDIA_TYPE_audio ||
 | 
			
		||||
	    info->info.media_subtype != SPA_MEDIA_SUBTYPE_raw)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) {
 | 
			
		||||
		if (format_info[i].format == info->info.info.raw.format)
 | 
			
		||||
			return &format_info[i];
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int open_write(struct wav_file *wf, const char *filename, struct wav_file_info *info)
 | 
			
		||||
{
 | 
			
		||||
	int res;
 | 
			
		||||
	const struct format_info *fi;
 | 
			
		||||
 | 
			
		||||
	fi = find_info(info);
 | 
			
		||||
	if (fi == NULL)
 | 
			
		||||
		return -ENOTSUP;
 | 
			
		||||
 | 
			
		||||
	if ((wf->fd = open(filename, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0660)) < 0) {
 | 
			
		||||
		res = -errno;
 | 
			
		||||
		goto exit;
 | 
			
		||||
	}
 | 
			
		||||
	wf->info = info->info;
 | 
			
		||||
	wf->fi = fi;
 | 
			
		||||
	if (fi->planar) {
 | 
			
		||||
		wf->stride = fi->bits / 8;
 | 
			
		||||
		wf->blocks = info->info.info.raw.channels;
 | 
			
		||||
	} else {
 | 
			
		||||
		wf->stride = info->info.info.raw.channels * (fi->bits / 8);
 | 
			
		||||
		wf->blocks = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res = write_headers(wf);
 | 
			
		||||
exit:
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wav_file *
 | 
			
		||||
wav_file_open(const char *filename, const char *mode, struct wav_file_info *info)
 | 
			
		||||
{
 | 
			
		||||
	int res;
 | 
			
		||||
	struct wav_file *wf;
 | 
			
		||||
 | 
			
		||||
	wf = calloc(1, sizeof(struct wav_file));
 | 
			
		||||
	if (wf == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (spa_streq(mode, "w")) {
 | 
			
		||||
		if ((res = open_write(wf, filename, info)) < 0)
 | 
			
		||||
			goto exit_free;
 | 
			
		||||
	} else {
 | 
			
		||||
		res = -EINVAL;
 | 
			
		||||
		goto exit_free;
 | 
			
		||||
	}
 | 
			
		||||
	return wf;
 | 
			
		||||
 | 
			
		||||
exit_free:
 | 
			
		||||
	free(wf);
 | 
			
		||||
	errno = -res;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int wav_file_close(struct wav_file *wf)
 | 
			
		||||
{
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	CHECK_RES(write_headers(wf));
 | 
			
		||||
 | 
			
		||||
	close(wf->fd);
 | 
			
		||||
	free(wf);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t wav_file_write(struct wav_file *wf, void **data, size_t samples)
 | 
			
		||||
{
 | 
			
		||||
	return wf->fi->write(wf, data, samples);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								spa/plugins/audioconvert/wavfile.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								spa/plugins/audioconvert/wavfile.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
/* PipeWire
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright © 2022 Wim Taymans
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
 * copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
 * to deal in the Software without restriction, including without limitation
 | 
			
		||||
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
 * Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice (including the next
 | 
			
		||||
 * paragraph) shall be included in all copies or substantial portions of the
 | 
			
		||||
 * Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
			
		||||
 * DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include <spa/utils/defs.h>
 | 
			
		||||
#include <spa/param/audio/format.h>
 | 
			
		||||
 | 
			
		||||
struct wav_file;
 | 
			
		||||
 | 
			
		||||
struct wav_file_info {
 | 
			
		||||
	struct spa_audio_info info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct wav_file *
 | 
			
		||||
wav_file_open(const char *filename, const char *mode, struct wav_file_info *info);
 | 
			
		||||
 | 
			
		||||
int wav_file_close(struct wav_file *wf);
 | 
			
		||||
 | 
			
		||||
ssize_t wav_file_write(struct wav_file *wf, void **data, size_t size);
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue