Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 11
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Mon Jul 11 18:00:28 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.54 + +------------------------------------------------------------------- Thu Jul 7 18:13:40 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.53
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.53 +Version: 0.3.54 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.53.tar.gz/NEWS -> pipewire-0.3.54.tar.gz/NEWS
Changed
@@ -1,3 +1,55 @@ +# PipeWire 0.3.54 (2022-07-07) + +This is a quick bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Some critical bugs in the new audioconvert were fixed. The old + adapter had internal buffering that was abused in some places. + - The bluetooth sources were rewritten using a ringbuffer to make them + more reliable to jitter and remove old audioconvert behaviour. + - Many improvements to the audio converter. + - Native DSD128 and up is now supported by pw-dsdplay. + + +## tools + - Support DSD128 to DSD512 as well by scaling the amount of samples + to read per time slice. + +## SPA + - Format conversion is now generated with macros to remove duplication + of code. + - 24bits conversions were rewritten to use the generic conversion + functions. + - Temporary buffers in audioconvert are now made large enough in all + cases. + - Fix draining in audioconvert. This fixes speaker-test. + - Fix the channel remapping. (#2502, #2490) + - Audio conversion constants were tweaked to handle the maximum ranges + and provide lossless conversion between 24bits and floats. + - Vector code and C code are aligned and the unit tests are activated + again. A new lossless conversion test was added. + - Fix an underrun case where the adapter would not ask for more data. + - Fix PROP_INFO for audioconvert. (#2488) + - Use the blackman window again for the resampler, the cosh window has + some bugs that can cause distortion in some cases. (#2483) + - Add more unit tests for audioconvert. Add end-to-end conversion tests. + - Don't leak memory in format converter. + +## pulse-server + - Card properties are now also added to sinks and sources, just like + in pulseaudio. + - Increase the maxlength size to at least 4 times the fragsize to avoid + xruns. + - Fix a race when setting default devices. + +## Bluetooth + - The source was rewritten to use a ringbuffer. This avoids regressions + caused by audioconvert. + +Older versions: + + # PipeWire 0.3.53 (2022-06-30) This is a bugfix release that is API and ABI compatible with previous @@ -74,8 +126,6 @@ giving a -19 nice level to all processes, not just the pipewire daemon. -Older versions: - # PipeWire 0.3.52 (2022-06-09) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.53.tar.gz/meson.build -> pipewire-0.3.54.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.53', + version : '0.3.54', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.59.0', default_options : 'warning_level=3',
View file
pipewire-0.3.53.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.54.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
@@ -726,6 +726,7 @@ { snd_pcm_pipewire_t *pw = io->private_data; + pw_thread_loop_lock(pw->main_loop); if (pw->stream) { snd_pcm_uframes_t min_avail; snd_pcm_sw_params_get_avail_min( sw_params, &min_avail); @@ -746,6 +747,7 @@ } else { pw_log_debug("%p: sw_params pre-prepare noop", pw); } + pw_thread_loop_unlock(pw->main_loop); return 0; }
View file
pipewire-0.3.53.tar.gz/po/hr.po -> pipewire-0.3.54.tar.gz/po/hr.po
Changed
@@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: pipewire\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-03 12:56+0200\n" -"PO-Revision-Date: 2022-04-03 12:57+0200\n" +"POT-Creation-Date: 2022-06-30 12:50+0200\n" +"PO-Revision-Date: 2022-06-30 13:14+0200\n" "Last-Translator: gogo <trebelnik2@gmail.com>\n" "Language-Team: Croatian <https://translate.fedoraproject.org/projects/" "pipewire/pipewire/hr/>\n" @@ -34,8 +34,8 @@ " --version Prikaži inačicu\n" " -c, --config Učitaj podešavanje (Zadano %s)\n" -#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:190 -#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:190 +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180 #, c-format msgid "Tunnel to %s/%s" msgstr "Tunel do %s/%s" @@ -44,41 +44,41 @@ msgid "Dummy Output" msgstr "Lažni izlaz" -#: src/modules/module-pulse-tunnel.c:545 +#: src/modules/module-pulse-tunnel.c:648 #, c-format msgid "Tunnel for %s@%s" msgstr "Tunel za %s@%s" -#: src/modules/module-zeroconf-discover.c:313 +#: src/modules/module-zeroconf-discover.c:332 msgid "Unknown device" msgstr "Nepoznat uređaj" -#: src/modules/module-zeroconf-discover.c:325 +#: src/modules/module-zeroconf-discover.c:344 #, c-format msgid "%s on %s@%s" msgstr "%s na %s@%s" -#: src/modules/module-zeroconf-discover.c:329 +#: src/modules/module-zeroconf-discover.c:348 #, c-format msgid "%s on %s" msgstr "%s na %s" -#: src/tools/pw-cat.c:1087 +#: src/tools/pw-cat.c:784 #, c-format msgid "" -"%s options <file>\n" +"%s options <file>|-\n" " -h, --help Show this help\n" " --version Show version\n" " -v, --verbose Enable verbose operations\n" "\n" msgstr "" -"%s mogućnosti <datoteka>\n" +"%s mogućnosti <datoteka>|-\n" " -h, --help Prikaži ovu pomoć\n" " --version Prikaži inačicu\n" " -v, --verbose Omogući opširnije radnje\n" "\n" -#: src/tools/pw-cat.c:1094 +#: src/tools/pw-cat.c:791 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -92,7 +92,7 @@ " or direct samples (256)\n" " the rate is the one of the source " "file\n" -" --list-targets List available targets for --target\n" +" -P --properties Set node properties\n" "\n" msgstr "" " -R, --remote Naziv udaljenog pozadinskog " @@ -111,11 +111,10 @@ " ili izravne uzorke (256)\n" " frekvencija je jednaka izvornoj " "datoteci\n" -" --list-targets Prikaži dostupna odredišta za --" -"target\n" +" -P --properties Postavi svojstva čvora\n" "\n" -#: src/tools/pw-cat.c:1112 +#: src/tools/pw-cat.c:809 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -151,7 +150,7 @@ "15) (zadano je %d)\n" "\n" -#: src/tools/pw-cat.c:1129 +#: src/tools/pw-cat.c:826 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" @@ -165,7 +164,7 @@ " -d, --dsd DSD način\n" "\n" -#: src/tools/pw-cli.c:3051 +#: src/tools/pw-cli.c:3165 #, c-format msgid "" "%s options command\n" @@ -188,8 +187,8 @@ msgid "Pro Audio" msgstr "Pro Audio" -#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648 -#: spa/plugins/bluez5/bluez5-device.c:1159 +#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1161 msgid "Off" msgstr "Isključeno" @@ -216,7 +215,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:2657 #: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:1328 +#: spa/plugins/bluez5/bluez5-device.c:1330 msgid "Microphone" msgstr "Mikrofon" @@ -282,7 +281,7 @@ msgstr "Bez pojačanja basa" #: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:1333 +#: spa/plugins/bluez5/bluez5-device.c:1335 msgid "Speaker" msgstr "Zvučnik" @@ -397,7 +396,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:4484 #: spa/plugins/alsa/acp/alsa-mixer.c:4642 -#: spa/plugins/bluez5/bluez5-device.c:1318 +#: spa/plugins/bluez5/bluez5-device.c:1320 msgid "Headset" msgstr "Slušalice s mikrofonom" @@ -521,8 +520,7 @@ msgid "%s Input" msgstr "%s ulaz" -#: spa/plugins/alsa/acp/alsa-util.c:1173 -#: spa/plugins/alsa/acp/alsa-util.c:1267 +#: spa/plugins/alsa/acp/alsa-util.c:1173 spa/plugins/alsa/acp/alsa-util.c:1267 #, c-format msgid "" "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu " @@ -619,7 +617,7 @@ "Najvjerojatnije je ovo greška ALSA upravljačkog programa '%s'. Prijavite " "problem ALSA razvijateljima." -#: spa/plugins/alsa/acp/channelmap.h:464 +#: spa/plugins/alsa/acp/channelmap.h:457 msgid "(invalid)" msgstr "(neispravno)" @@ -631,62 +629,62 @@ msgid "Modem" msgstr "Modem" -#: spa/plugins/bluez5/bluez5-device.c:1170 +#: spa/plugins/bluez5/bluez5-device.c:1172 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" msgstr "Zvučni pristupnik (A2DP izvor i HSP/HFP AG)" -#: spa/plugins/bluez5/bluez5-device.c:1195 +#: spa/plugins/bluez5/bluez5-device.c:1197 #, c-format msgid "High Fidelity Playback (A2DP Sink, codec %s)" msgstr "Reprodukcija visoke autentičnosti (A2DP slivnik, kôdek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1198 +#: spa/plugins/bluez5/bluez5-device.c:1200 #, c-format msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" msgstr "Telefonija visoke autentičnosti (A2DP slivnik, kôdek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1206 +#: spa/plugins/bluez5/bluez5-device.c:1208 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Reprodukcija visoke autentičnosti (A2DP slivnik)" -#: spa/plugins/bluez5/bluez5-device.c:1208 +#: spa/plugins/bluez5/bluez5-device.c:1210 msgid "High Fidelity Duplex (A2DP Source/Sink)" msgstr "Telefonija visoke autentičnosti (A2DP izvor/slivnik)" -#: spa/plugins/bluez5/bluez5-device.c:1236 +#: spa/plugins/bluez5/bluez5-device.c:1238 #, c-format msgid "Headset Head Unit (HSP/HFP, codec %s)" msgstr "Jedinica slušalice s mikrofonom (HSP/HFP, kôdek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1241 +#: spa/plugins/bluez5/bluez5-device.c:1243 msgid "Headset Head Unit (HSP/HFP)" msgstr "Jedinica slušalice s mikrofonom (HSP/HFP)" -#: spa/plugins/bluez5/bluez5-device.c:1323 +#: spa/plugins/bluez5/bluez5-device.c:1325 msgid "Handsfree" msgstr "Bez-ruku" -#: spa/plugins/bluez5/bluez5-device.c:1338 +#: spa/plugins/bluez5/bluez5-device.c:1340 msgid "Headphone" msgstr "Slušalice" -#: spa/plugins/bluez5/bluez5-device.c:1343 +#: spa/plugins/bluez5/bluez5-device.c:1345 msgid "Portable" msgstr "Prijenosnik" -#: spa/plugins/bluez5/bluez5-device.c:1348 +#: spa/plugins/bluez5/bluez5-device.c:1350 msgid "Car" msgstr "Automobil" -#: spa/plugins/bluez5/bluez5-device.c:1353 +#: spa/plugins/bluez5/bluez5-device.c:1355 msgid "HiFi" msgstr "HiFi" -#: spa/plugins/bluez5/bluez5-device.c:1358 +#: spa/plugins/bluez5/bluez5-device.c:1360 msgid "Phone" msgstr "Telefon" -#: spa/plugins/bluez5/bluez5-device.c:1364 +#: spa/plugins/bluez5/bluez5-device.c:1366 msgid "Bluetooth" msgstr "Bluetooth"
View file
pipewire-0.3.53.tar.gz/po/pipewire.pot -> pipewire-0.3.54.tar.gz/po/pipewire.pot
Changed
@@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: pipewire\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/issues/new\n" -"POT-Creation-Date: 2022-04-03 12:56+0200\n" +"POT-Creation-Date: 2022-06-30 12:50+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -27,8 +27,8 @@ " -c, --config Load config (Default %s)\n" msgstr "" -#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:190 -#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:190 +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180 #, c-format msgid "Tunnel to %s/%s" msgstr "" @@ -37,36 +37,36 @@ msgid "Dummy Output" msgstr "" -#: src/modules/module-pulse-tunnel.c:545 +#: src/modules/module-pulse-tunnel.c:648 #, c-format msgid "Tunnel for %s@%s" msgstr "" -#: src/modules/module-zeroconf-discover.c:313 +#: src/modules/module-zeroconf-discover.c:332 msgid "Unknown device" msgstr "" -#: src/modules/module-zeroconf-discover.c:325 +#: src/modules/module-zeroconf-discover.c:344 #, c-format msgid "%s on %s@%s" msgstr "" -#: src/modules/module-zeroconf-discover.c:329 +#: src/modules/module-zeroconf-discover.c:348 #, c-format msgid "%s on %s" msgstr "" -#: src/tools/pw-cat.c:1087 +#: src/tools/pw-cat.c:784 #, c-format msgid "" -"%s options <file>\n" +"%s options <file>|-\n" " -h, --help Show this help\n" " --version Show version\n" " -v, --verbose Enable verbose operations\n" "\n" msgstr "" -#: src/tools/pw-cat.c:1094 +#: src/tools/pw-cat.c:791 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -80,11 +80,11 @@ " or direct samples (256)\n" " the rate is the one of the source " "file\n" -" --list-targets List available targets for --target\n" +" -P --properties Set node properties\n" "\n" msgstr "" -#: src/tools/pw-cat.c:1112 +#: src/tools/pw-cat.c:809 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -104,7 +104,7 @@ "\n" msgstr "" -#: src/tools/pw-cat.c:1129 +#: src/tools/pw-cat.c:826 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" @@ -113,7 +113,7 @@ "\n" msgstr "" -#: src/tools/pw-cli.c:3051 +#: src/tools/pw-cli.c:3165 #, c-format msgid "" "%s options command\n" @@ -128,8 +128,8 @@ msgid "Pro Audio" msgstr "" -#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648 -#: spa/plugins/bluez5/bluez5-device.c:1159 +#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1161 msgid "Off" msgstr "" @@ -156,7 +156,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:2657 #: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:1328 +#: spa/plugins/bluez5/bluez5-device.c:1330 msgid "Microphone" msgstr "" @@ -222,7 +222,7 @@ msgstr "" #: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:1333 +#: spa/plugins/bluez5/bluez5-device.c:1335 msgid "Speaker" msgstr "" @@ -337,7 +337,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:4484 #: spa/plugins/alsa/acp/alsa-mixer.c:4642 -#: spa/plugins/bluez5/bluez5-device.c:1318 +#: spa/plugins/bluez5/bluez5-device.c:1320 msgid "Headset" msgstr "" @@ -516,7 +516,7 @@ msgstr0 "" msgstr1 "" -#: spa/plugins/alsa/acp/channelmap.h:464 +#: spa/plugins/alsa/acp/channelmap.h:457 msgid "(invalid)" msgstr "" @@ -528,61 +528,61 @@ msgid "Modem" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1170 +#: spa/plugins/bluez5/bluez5-device.c:1172 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1195 +#: spa/plugins/bluez5/bluez5-device.c:1197 #, c-format msgid "High Fidelity Playback (A2DP Sink, codec %s)" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1198 +#: spa/plugins/bluez5/bluez5-device.c:1200 #, c-format msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1206 +#: spa/plugins/bluez5/bluez5-device.c:1208 msgid "High Fidelity Playback (A2DP Sink)" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1208 +#: spa/plugins/bluez5/bluez5-device.c:1210 msgid "High Fidelity Duplex (A2DP Source/Sink)" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1236 +#: spa/plugins/bluez5/bluez5-device.c:1238 #, c-format msgid "Headset Head Unit (HSP/HFP, codec %s)" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1241 +#: spa/plugins/bluez5/bluez5-device.c:1243 msgid "Headset Head Unit (HSP/HFP)" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1323 +#: spa/plugins/bluez5/bluez5-device.c:1325 msgid "Handsfree" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1338 +#: spa/plugins/bluez5/bluez5-device.c:1340 msgid "Headphone" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1343 +#: spa/plugins/bluez5/bluez5-device.c:1345 msgid "Portable" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1348 +#: spa/plugins/bluez5/bluez5-device.c:1350 msgid "Car" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1353 +#: spa/plugins/bluez5/bluez5-device.c:1355 msgid "HiFi" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1358 +#: spa/plugins/bluez5/bluez5-device.c:1360 msgid "Phone" msgstr "" -#: spa/plugins/bluez5/bluez5-device.c:1364 +#: spa/plugins/bluez5/bluez5-device.c:1366 msgid "Bluetooth" msgstr ""
View file
pipewire-0.3.53.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.54.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
@@ -707,6 +707,7 @@ this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; this->port_paramsPORT_Latency.user++; emit_port_info(this, false); + res = 0; break; } default:
View file
pipewire-0.3.53.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.54.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -752,7 +752,7 @@ } static int add_rate(struct state *state, uint32_t scale, bool all, uint32_t index, uint32_t *next, - snd_pcm_hw_params_t *params, struct spa_pod_builder *b) + uint32_t min_allowed_rate, snd_pcm_hw_params_t *params, struct spa_pod_builder *b) { struct spa_pod_frame f1; int err, dir; @@ -763,6 +763,9 @@ CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min"); CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max"); + min_allowed_rate /= scale; + min = SPA_MAX(min_allowed_rate, min); + if (!state->multi_rate && state->card->format_ref > 0) rate = state->card->rate; else @@ -1017,7 +1020,7 @@ choice->body.type = SPA_CHOICE_Enum; spa_pod_builder_pop(b, &f1); - if ((res = add_rate(state, 1, false, index & 0xffff, next, params, b)) != 1) + if ((res = add_rate(state, 1, false, index & 0xffff, next, 0, params, b)) != 1) return res; if ((res = add_channels(state, false, index & 0xffff, next, params, b)) != 1) @@ -1110,7 +1113,7 @@ } spa_pod_builder_pop(b, &f1); - if ((res = add_rate(state, 1, true, index & 0xffff, next, params, b)) != 1) + if ((res = add_rate(state, 1, true, index & 0xffff, next, 0, params, b)) != 1) return res; (*next)++; @@ -1165,7 +1168,14 @@ spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_interleave, 0); spa_pod_builder_int(b, interleave); - if ((res = add_rate(state, SPA_ABS(interleave), true, index & 0xffff, next, params, b)) != 1) + /* Use a lower rate limit of 352800 (= 44100 * 64 / 8). This is because in + * PipeWire, DSD rates are given in bytes, not bits, so 352800 corresponds + * to the bit rate of DSD64. (The "64" in DSD64 means "64 times the rate + * of 44.1 kHz".) Some hardware may report rates lower than that, for example + * 176400. This would correspond to "DSD32" (which does not exist). Trying + * to use such a rate with DSD hardware does not work and may cause undefined + * behavior in said hardware. */ + if ((res = add_rate(state, SPA_ABS(interleave), true, index & 0xffff, next, 44100 * 64 / 8, params, b)) != 1) return res; if ((res = add_channels(state, true, index & 0xffff, next, params, b)) != 1)
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -1153,8 +1153,21 @@ if (this->target != this->follower) { this->driver = true; - if (this->direction == SPA_DIRECTION_OUTPUT) - status = spa_node_process(this->convert); + if (this->direction == SPA_DIRECTION_OUTPUT) { + int retry = 8; + while (retry--) { + status = spa_node_process(this->convert); + if (status & SPA_STATUS_HAVE_DATA) + break; + + if (status & SPA_STATUS_NEED_DATA) { + status = spa_node_process(this->follower); + if (!(status & SPA_STATUS_HAVE_DATA)) + break; + } + } + + } } return spa_node_call_ready(&this->callbacks, status);
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -166,10 +166,10 @@ unsigned int have_profile:1; struct spa_latency_info latency; - uint32_t src_remapMAX_PORTS; - uint32_t dst_remapMAX_PORTS; + uint32_t remapMAX_PORTS; struct convert conv; + unsigned int need_remap:1; unsigned int is_passthrough:1; unsigned int control:1; }; @@ -221,9 +221,7 @@ uint32_t empty_size; float *empty; float *scratch; - float *tmp; - float *tmp2; - + float *tmp2; float *tmp_datas2MAX_PORTS; }; @@ -438,21 +436,21 @@ param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_volume), - SPA_PROP_INFO_name, SPA_POD_String("Volume"), + SPA_PROP_INFO_description, SPA_POD_String("Volume"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(p->volume, 0.0, 10.0)); break; case 1: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_mute), - SPA_PROP_INFO_name, SPA_POD_String("Mute"), + SPA_PROP_INFO_description, SPA_POD_String("Mute"), SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->channel.mute)); break; case 2: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_channelVolumes), - SPA_PROP_INFO_name, SPA_POD_String("Channel Volumes"), + SPA_PROP_INFO_description, SPA_POD_String("Channel Volumes"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(p->volume, 0.0, 10.0), SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array)); break; @@ -460,7 +458,7 @@ param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_channelMap), - SPA_PROP_INFO_name, SPA_POD_String("Channel Map"), + SPA_PROP_INFO_description, SPA_POD_String("Channel Map"), SPA_PROP_INFO_type, SPA_POD_Id(SPA_AUDIO_CHANNEL_UNKNOWN), SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array)); break; @@ -468,14 +466,14 @@ param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_monitorMute), - SPA_PROP_INFO_name, SPA_POD_String("Monitor Mute"), + SPA_PROP_INFO_description, SPA_POD_String("Monitor Mute"), SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->monitor.mute)); break; case 5: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_monitorVolumes), - SPA_PROP_INFO_name, SPA_POD_String("Monitor Volumes"), + SPA_PROP_INFO_description, SPA_POD_String("Monitor Volumes"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(p->volume, 0.0, 10.0), SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array)); break; @@ -483,14 +481,14 @@ param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_softMute), - SPA_PROP_INFO_name, SPA_POD_String("Soft Mute"), + SPA_PROP_INFO_description, SPA_POD_String("Soft Mute"), SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->soft.mute)); break; case 7: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_softVolumes), - SPA_PROP_INFO_name, SPA_POD_String("Soft Volumes"), + SPA_PROP_INFO_description, SPA_POD_String("Soft Volumes"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(p->volume, 0.0, 10.0), SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array)); break; @@ -1104,6 +1102,7 @@ struct dir *in = &this->dirSPA_DIRECTION_INPUT; struct spa_audio_info src_info, dst_info; int res; + bool remap = false; src_info = in->format; dst_info = src_info; @@ -1125,10 +1124,11 @@ if (src_info.info.raw.positioni != dst_info.info.raw.positionj) continue; - in->src_remapi = j; - in->dst_remapj = i; - spa_log_debug(this->log, "%p: channel %d -> %d (%s -> %s)", this, - i, j, + in->remapi = j; + if (i != j) + remap = true; + spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this, + i, in->remapi, j, spa_debug_type_find_short_name(spa_type_audio_channel, src_info.info.raw.positioni), spa_debug_type_find_short_name(spa_type_audio_channel, @@ -1137,17 +1137,21 @@ break; } } + if (in->conv.free) + convert_free(&in->conv); + in->conv.src_fmt = src_info.info.raw.format; in->conv.dst_fmt = dst_info.info.raw.format; in->conv.n_channels = dst_info.info.raw.channels; in->conv.cpu_flags = this->cpu_flags; + in->need_remap = remap; if ((res = convert_init(&in->conv)) < 0) return res; - spa_log_debug(this->log, "%p: got converter features %08x:%08x passthrough:%d %s", this, + spa_log_debug(this->log, "%p: got converter features %08x:%08x passthrough:%d remap:%d %s", this, this->cpu_flags, in->conv.cpu_flags, in->conv.is_passthrough, - in->conv.func_name); + remap, in->conv.func_name); return 0; } @@ -1266,7 +1270,7 @@ vol = &this->props.channel; for (i = 0; i < vol->n_volumes; i++) - volumesi = vol->volumesdir->src_remapi; + volumesi = vol->volumesdir->remapi; channelmix_set_volume(&this->mix, this->props.volume, vol->mute, vol->n_volumes, volumes); @@ -1396,6 +1400,7 @@ struct dir *out = &this->dirSPA_DIRECTION_OUTPUT; struct spa_audio_info src_info, dst_info; int res; + bool remap = false; dst_info = out->format; src_info = dst_info; @@ -1417,10 +1422,12 @@ if (src_info.info.raw.positioni != dst_info.info.raw.positionj) continue; - out->src_remapi = j; - out->dst_remapj = i; - spa_log_debug(this->log, "%p: channel %d -> %d (%s -> %s)", this, - i, j, + out->remapi = j; + if (i != j) + remap = true; + + spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this, + i, out->remapi, j, spa_debug_type_find_short_name(spa_type_audio_channel, src_info.info.raw.positioni), spa_debug_type_find_short_name(spa_type_audio_channel, @@ -1429,20 +1436,23 @@ break; } } - out->conv.quantize = calc_width(&dst_info) * 8; + if (out->conv.free) + convert_free(&out->conv); + out->conv.src_fmt = src_info.info.raw.format; out->conv.dst_fmt = dst_info.info.raw.format; out->conv.rate = dst_info.info.raw.rate; out->conv.n_channels = dst_info.info.raw.channels; out->conv.cpu_flags = this->cpu_flags; + out->need_remap = remap; if ((res = convert_init(&out->conv)) < 0) return res; - spa_log_debug(this->log, "%p: got converter features %08x:%08x quant:%d:%d:%d passthrough:%d %s", this, + spa_log_debug(this->log, "%p: got converter features %08x:%08x quant:%d:%d" + " passthrough:%d remap:%d %s", this, this->cpu_flags, out->conv.cpu_flags, out->conv.method, - out->conv.quantize, out->conv.noise, - out->conv.is_passthrough, out->conv.func_name); + out->conv.noise, out->conv.is_passthrough, remap, out->conv.func_name); return 0; } @@ -1491,9 +1501,9 @@ return res; for (i = 0; i < MAX_PORTS; i++) { - this->tmp_datas0i = SPA_PTROFF(this->tmp, this->empty_size * i, void); + this->tmp_datas0i = SPA_PTROFF(this->tmp0, this->empty_size * i, void); this->tmp_datas0i = SPA_PTR_ALIGN(this->tmp_datas0i, MAX_ALIGN, void); - this->tmp_datas1i = SPA_PTROFF(this->tmp2, this->empty_size * i, void); + this->tmp_datas1i = SPA_PTROFF(this->tmp1, this->empty_size * i, void); this->tmp_datas1i = SPA_PTR_ALIGN(this->tmp_datas1i, MAX_ALIGN, void); } @@ -2009,7 +2019,8 @@ clear_buffers(this, port); - maxsize = 0; + maxsize = this->quantum_limit * sizeof(float); + for (i = 0; i < n_buffers; i++) { struct buffer *b; uint32_t n_datas = buffersi->n_datas; @@ -2050,10 +2061,10 @@ if (maxsize > this->empty_size) { this->empty = realloc(this->empty, maxsize + MAX_ALIGN); this->scratch = realloc(this->scratch, maxsize + MAX_ALIGN); - this->tmp = realloc(this->tmp, (4 * maxsize + MAX_ALIGN) * MAX_PORTS); - this->tmp2 = realloc(this->tmp2, (4 * maxsize + MAX_ALIGN) * MAX_PORTS); + this->tmp0 = realloc(this->tmp0, (maxsize + MAX_ALIGN) * MAX_PORTS); + this->tmp1 = realloc(this->tmp1, (maxsize + MAX_ALIGN) * MAX_PORTS); if (this->empty == NULL || this->scratch == NULL || - this->tmp == NULL || this->tmp2 == NULL) + this->tmp0 == NULL || this->tmp1 == NULL) return -errno; memset(this->empty, 0, maxsize + MAX_ALIGN); this->empty_size = maxsize; @@ -2221,7 +2232,8 @@ { struct impl *this = object; const void *src_datasMAX_PORTS, **in_datas; - void *dst_datasMAX_PORTS, **out_datas; + void *dst_datasMAX_PORTS, *remap_src_datasMAX_PORTS, *remap_dst_datasMAX_PORTS; + void **out_datas, **dst_remap; uint32_t i, j, n_src_datas = 0, n_dst_datas = 0, n_mon_datas = 0, remap; uint32_t n_samples, max_in, n_out, max_out, quant_samples; struct port *port, *ctrlport = NULL; @@ -2229,14 +2241,13 @@ struct spa_data *bd; struct dir *dir; int tmp = 0, res = 0; - bool in_passthrough, mix_passthrough, resample_passthrough, out_passthrough, end_passthrough; + bool in_passthrough, mix_passthrough, resample_passthrough, out_passthrough; bool in_avail = false, flush_in = false, flush_out = false, draining = false, in_empty = true; struct spa_io_buffers *io, *ctrlio = NULL; const struct spa_pod_sequence *ctrl = NULL; dir = &this->dirSPA_DIRECTION_INPUT; in_passthrough = dir->conv.is_passthrough; - max_in = UINT32_MAX; /* collect input port data */ @@ -2255,6 +2266,7 @@ spa_log_trace_fp(this->log, "%p: empty input port %d %p %d %d %d", this, port->id, io, io->status, io->buffer_id, port->n_buffers); + this->drained = false; } buf = NULL; } else if (SPA_UNLIKELY(io->buffer_id >= port->n_buffers)) { @@ -2264,6 +2276,9 @@ io->status = -EINVAL; buf = NULL; } else { + spa_log_trace_fp(this->log, "%p: input buffer port %d io:%p status:%d id:%d n:%d", + this, port->id, io, io->status, io->buffer_id, + port->n_buffers); buf = &port->buffersio->buffer_id; } @@ -2273,7 +2288,7 @@ spa_log_trace_fp(this->log, "%p: empty control %d", this, i * port->blocks + j); } else { - remap = dir->src_remapn_src_datas++; + remap = n_src_datas++; src_datasremap = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); spa_log_trace_fp(this->log, "%p: empty input %d->%d", this, i * port->blocks + j, remap); @@ -2308,7 +2323,7 @@ } else { max_in = SPA_MIN(max_in, size / port->stride); - remap = dir->src_remapn_src_datas++; + remap = n_src_datas++; offs += this->in_offset * port->stride; src_datasremap = SPA_PTROFF(bd->data, offs, void); @@ -2374,8 +2389,6 @@ } dir = &this->dirSPA_DIRECTION_OUTPUT; - out_passthrough = dir->conv.is_passthrough; - /* collect output ports and monitor ports data */ for (i = 0; i < dir->n_ports; i++) { port = GET_OUT_PORT(this, i); @@ -2401,7 +2414,7 @@ } else if (port->is_control) { spa_log_trace_fp(this->log, "%p: empty control %d", this, j); } else { - remap = dir->dst_remapn_dst_datas++; + remap = n_dst_datas++; dst_datasremap = SPA_PTR_ALIGN(this->scratch, MAX_ALIGN, void); spa_log_trace_fp(this->log, "%p: empty output %d->%d", this, i * port->blocks + j, remap); @@ -2440,7 +2453,7 @@ } else if (SPA_UNLIKELY(port->is_control)) { spa_log_trace_fp(this->log, "%p: control %d", this, j); } else { - remap = dir->dst_remapn_dst_datas++; + remap = n_dst_datas++; dst_datasremap = SPA_PTROFF(bd->data, this->out_offset * port->stride, void); max_out = SPA_MIN(max_out, bd->maxsize / port->stride); @@ -2452,34 +2465,54 @@ } } } - - n_out = max_out - SPA_MIN(max_out, this->out_offset); - mix_passthrough = SPA_FLAG_IS_SET(this->mix.flags, CHANNELMIX_FLAG_IDENTITY) && (ctrlport == NULL || ctrlport->ctrl == NULL); - end_passthrough = mix_passthrough && resample_passthrough && out_passthrough; - if (!in_passthrough || end_passthrough) { - if (end_passthrough) { - out_datas = (void **)dst_datas; - n_samples = SPA_MIN(n_samples, n_out); + out_passthrough = dir->conv.is_passthrough; + if (in_passthrough && mix_passthrough && resample_passthrough) + out_passthrough = false; + + if (out_passthrough && dir->need_remap) { + for (i = 0; i < dir->conv.n_channels; i++) { + remap_dst_datasi = dst_datasdir->remapi; + spa_log_trace_fp(this->log, "%p: output remap %d -> %d", this, i, dir->remapi); } + dst_remap = (void **)remap_dst_datas; + } else { + dst_remap = (void **)dst_datas; + } + + n_out = max_out - SPA_MIN(max_out, this->out_offset); + + dir = &this->dirSPA_DIRECTION_INPUT; + if (!in_passthrough) { + if (mix_passthrough && resample_passthrough && out_passthrough) + out_datas = (void **)dst_remap; else out_datas = (void **)this->tmp_datas(tmp++) & 1; - spa_log_trace_fp(this->log, "%p: convert %d %d", this, n_samples, end_passthrough); - convert_process(&this->dirSPA_DIRECTION_INPUT.conv, out_datas, src_datas, n_samples); } else { out_datas = (void **)src_datas; } + if (dir->need_remap) { + for (i = 0; i < dir->conv.n_channels; i++) { + remap_src_datasi = out_datasdir->remapi; + spa_log_trace_fp(this->log, "%p: input remap %d -> %d", this, dir->remapi, i); + } + out_datas = (void **)remap_src_datas; + } + if (!in_passthrough) { + spa_log_trace_fp(this->log, "%p: input convert %d", this, n_samples); + convert_process(&dir->conv, out_datas, src_datas, n_samples); + } if (!mix_passthrough) { in_datas = (const void**)out_datas; if (resample_passthrough && out_passthrough) { - out_datas = (void **)dst_datas; + out_datas = (void **)dst_remap; n_samples = SPA_MIN(n_samples, n_out); - } - else + } else { out_datas = (void **)this->tmp_datas(tmp++) & 1; + } spa_log_trace_fp(this->log, "%p: channelmix %d %d %d", this, n_samples, resample_passthrough, out_passthrough); if (ctrlport != NULL && ctrlport->ctrl != NULL) { @@ -2492,13 +2525,12 @@ channelmix_process(&this->mix, out_datas, in_datas, n_samples); } } - if (!resample_passthrough) { uint32_t in_len, out_len; in_datas = (const void**)out_datas; if (out_passthrough) - out_datas = (void **)dst_datas; + out_datas = (void **)dst_remap; else out_datas = (void **)this->tmp_datas(tmp++) & 1; @@ -2516,9 +2548,18 @@ this->out_offset += n_samples; if (!out_passthrough) { - in_datas = (const void**)out_datas; - spa_log_trace_fp(this->log, "%p: convert %d", this, n_samples); - convert_process(&this->dirSPA_DIRECTION_OUTPUT.conv, dst_datas, in_datas, n_samples); + dir = &this->dirSPA_DIRECTION_OUTPUT; + if (dir->need_remap) { + for (i = 0; i < dir->conv.n_channels; i++) { + remap_dst_datasi = out_datasdir->remapi; + spa_log_trace_fp(this->log, "%p: output remap %d -> %d", this, i, dir->remapi); + } + in_datas = (const void**)remap_dst_datas; + } else { + in_datas = (const void**)out_datas; + } + spa_log_trace_fp(this->log, "%p: output convert %d", this, n_samples); + convert_process(&dir->conv, dst_datas, in_datas, n_samples); } spa_log_trace_fp(this->log, "%d/%d %d/%d %d->%d", this->in_offset, max_in, @@ -2534,7 +2575,8 @@ if (SPA_UNLIKELY((io = port->io) == NULL)) continue; spa_log_trace_fp(this->log, "return: input %d %d", port->id, io->buffer_id); - io->status = SPA_STATUS_NEED_DATA; + if (!draining) + io->status = SPA_STATUS_NEED_DATA; } this->in_offset = 0; max_in = 0; @@ -2641,11 +2683,15 @@ free(this->dirSPA_DIRECTION_OUTPUT.portsi); free(this->empty); free(this->scratch); - free(this->tmp); - free(this->tmp2); + free(this->tmp0); + free(this->tmp1); if (this->resample.free) resample_free(&this->resample); + if (this->dir0.conv.free) + convert_free(&this->dir0.conv); + if (this->dir1.conv.free) + convert_free(&this->dir1.conv); return 0; }
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/benchmark-fmt-ops.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/benchmark-fmt-ops.c
Changed
@@ -271,18 +271,18 @@ static void test_interleave(void) { - run_test("test_interleave_8", "c", false, true, conv_interleave_8_c); - run_test("test_interleave_16", "c", false, true, conv_interleave_16_c); - run_test("test_interleave_24", "c", false, true, conv_interleave_24_c); - run_test("test_interleave_32", "c", false, true, conv_interleave_32_c); + run_test("test_8d_to_8", "c", false, true, conv_8d_to_8_c); + run_test("test_16d_to_16", "c", false, true, conv_16d_to_16_c); + run_test("test_24d_to_24", "c", false, true, conv_24d_to_24_c); + run_test("test_32d_to_32", "c", false, true, conv_32d_to_32_c); } static void test_deinterleave(void) { - run_test("test_deinterleave_8", "c", true, false, conv_deinterleave_8_c); - run_test("test_deinterleave_16", "c", true, false, conv_deinterleave_16_c); - run_test("test_deinterleave_24", "c", true, false, conv_deinterleave_24_c); - run_test("test_deinterleave_32", "c", true, false, conv_deinterleave_32_c); + run_test("test_8_to_8d", "c", true, false, conv_8_to_8d_c); + run_test("test_16_to_16d", "c", true, false, conv_16_to_16d_c); + run_test("test_24_to_24d", "c", true, false, conv_24_to_24d_c); + run_test("test_32_to_32d", "c", true, false, conv_32_to_32d_c); } static int compare_func(const void *_a, const void *_b)
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c
Changed
@@ -147,7 +147,7 @@ conv_s24_to_f32d_1s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0; uint32_t n, unrolled; __m128i in; @@ -164,21 +164,21 @@ for(n = 0; n < unrolled; n += 4) { in = _mm_setr_epi32( *((uint32_t*)&s0 * n_channels), - *((uint32_t*)&s3 * n_channels), - *((uint32_t*)&s6 * n_channels), - *((uint32_t*)&s9 * n_channels)); + *((uint32_t*)&s1 * n_channels), + *((uint32_t*)&s2 * n_channels), + *((uint32_t*)&s3 * n_channels)); in = _mm_slli_epi32(in, 8); in = _mm_srai_epi32(in, 8); out = _mm_cvtepi32_ps(in); out = _mm_mul_ps(out, factor); _mm_store_ps(&d0n, out); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out = _mm_cvtsi32_ss(factor, read_s24(s)); + out = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); out = _mm_mul_ss(out, factor); _mm_store_ss(&d0n, out); - s += 3 * n_channels; + s += n_channels; } } @@ -186,7 +186,7 @@ conv_s24_to_f32d_2s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0, *d1 = dst1; uint32_t n, unrolled; __m128i in2; @@ -205,14 +205,14 @@ for(n = 0; n < unrolled; n += 4) { in0 = _mm_setr_epi32( *((uint32_t*)&s0 + 0*n_channels), - *((uint32_t*)&s0 + 3*n_channels), - *((uint32_t*)&s0 + 6*n_channels), - *((uint32_t*)&s0 + 9*n_channels)); + *((uint32_t*)&s0 + 1*n_channels), + *((uint32_t*)&s0 + 2*n_channels), + *((uint32_t*)&s0 + 3*n_channels)); in1 = _mm_setr_epi32( - *((uint32_t*)&s3 + 0*n_channels), - *((uint32_t*)&s3 + 3*n_channels), - *((uint32_t*)&s3 + 6*n_channels), - *((uint32_t*)&s3 + 9*n_channels)); + *((uint32_t*)&s1 + 0*n_channels), + *((uint32_t*)&s1 + 1*n_channels), + *((uint32_t*)&s1 + 2*n_channels), + *((uint32_t*)&s1 + 3*n_channels)); in0 = _mm_slli_epi32(in0, 8); in1 = _mm_slli_epi32(in1, 8); @@ -229,23 +229,23 @@ _mm_store_ps(&d0n, out0); _mm_store_ps(&d1n, out1); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out0 = _mm_cvtsi32_ss(factor, read_s24(s)); - out1 = _mm_cvtsi32_ss(factor, read_s24(s+3)); + out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); + out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+1))); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); _mm_store_ss(&d0n, out0); _mm_store_ss(&d1n, out1); - s += 3 * n_channels; + s += n_channels; } } static void conv_s24_to_f32d_4s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0, *d1 = dst1, *d2 = dst2, *d3 = dst3; uint32_t n, unrolled; __m128i in4; @@ -266,24 +266,24 @@ for(n = 0; n < unrolled; n += 4) { in0 = _mm_setr_epi32( *((uint32_t*)&s0 + 0*n_channels), - *((uint32_t*)&s0 + 3*n_channels), - *((uint32_t*)&s0 + 6*n_channels), - *((uint32_t*)&s0 + 9*n_channels)); + *((uint32_t*)&s0 + 1*n_channels), + *((uint32_t*)&s0 + 2*n_channels), + *((uint32_t*)&s0 + 3*n_channels)); in1 = _mm_setr_epi32( - *((uint32_t*)&s3 + 0*n_channels), - *((uint32_t*)&s3 + 3*n_channels), - *((uint32_t*)&s3 + 6*n_channels), - *((uint32_t*)&s3 + 9*n_channels)); + *((uint32_t*)&s1 + 0*n_channels), + *((uint32_t*)&s1 + 1*n_channels), + *((uint32_t*)&s1 + 2*n_channels), + *((uint32_t*)&s1 + 3*n_channels)); in2 = _mm_setr_epi32( - *((uint32_t*)&s6 + 0*n_channels), - *((uint32_t*)&s6 + 3*n_channels), - *((uint32_t*)&s6 + 6*n_channels), - *((uint32_t*)&s6 + 9*n_channels)); + *((uint32_t*)&s2 + 0*n_channels), + *((uint32_t*)&s2 + 1*n_channels), + *((uint32_t*)&s2 + 2*n_channels), + *((uint32_t*)&s2 + 3*n_channels)); in3 = _mm_setr_epi32( - *((uint32_t*)&s9 + 0*n_channels), - *((uint32_t*)&s9 + 3*n_channels), - *((uint32_t*)&s9 + 6*n_channels), - *((uint32_t*)&s9 + 9*n_channels)); + *((uint32_t*)&s3 + 0*n_channels), + *((uint32_t*)&s3 + 1*n_channels), + *((uint32_t*)&s3 + 2*n_channels), + *((uint32_t*)&s3 + 3*n_channels)); in0 = _mm_slli_epi32(in0, 8); in1 = _mm_slli_epi32(in1, 8); @@ -310,13 +310,13 @@ _mm_store_ps(&d2n, out2); _mm_store_ps(&d3n, out3); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out0 = _mm_cvtsi32_ss(factor, read_s24(s)); - out1 = _mm_cvtsi32_ss(factor, read_s24(s+3)); - out2 = _mm_cvtsi32_ss(factor, read_s24(s+6)); - out3 = _mm_cvtsi32_ss(factor, read_s24(s+9)); + out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); + out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+1))); + out2 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+2))); + out3 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+3))); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); out2 = _mm_mul_ss(out2, factor); @@ -325,7 +325,7 @@ _mm_store_ss(&d1n, out1); _mm_store_ss(&d2n, out2); _mm_store_ss(&d3n, out3); - s += 3 * n_channels; + s += n_channels; } } @@ -353,7 +353,7 @@ float *d0 = dst0, *d1 = dst1, *d2 = dst2, *d3 = dst3; uint32_t n, unrolled; __m256i in4, t4; - __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE); + __m256 out4, factor = _mm256_set1_ps(1.0f / S32_SCALE); __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 0*n_channels+2, 4*n_channels, 4*n_channels+2); __m256i mask2 = _mm256_setr_epi64x(1*n_channels, 1*n_channels+2, 5*n_channels, 5*n_channels+2); __m256i mask3 = _mm256_setr_epi64x(2*n_channels, 2*n_channels+2, 6*n_channels, 6*n_channels+2); @@ -373,11 +373,6 @@ in2 = _mm256_i64gather_epi64((long long int *)&s0*n_channels, mask3, 4); in3 = _mm256_i64gather_epi64((long long int *)&s0*n_channels, mask4, 4); - in0 = _mm256_srai_epi32(in0, 8); /* a0 b0 c0 d0 a4 b4 c4 d4 */ - in1 = _mm256_srai_epi32(in1, 8); /* a1 b1 c1 d1 a5 b5 c5 d5 */ - in2 = _mm256_srai_epi32(in2, 8); /* a2 b2 c2 d2 a6 b6 c6 d6 */ - in3 = _mm256_srai_epi32(in3, 8); /* a3 b3 c3 d3 a7 b7 c7 d7 */ - t0 = _mm256_unpacklo_epi32(in0, in1); /* a0 a1 b0 b1 a4 a5 b4 b5 */ t1 = _mm256_unpackhi_epi32(in0, in1); /* c0 c1 d0 d1 c4 c5 d4 d5 */ t2 = _mm256_unpacklo_epi32(in2, in3); /* a2 a3 b2 b3 a6 a7 b6 b7 */ @@ -405,11 +400,11 @@ s += 8*n_channels; } for(; n < n_samples; n++) { - __m128 out4, factor = _mm_set1_ps(1.0f / S24_SCALE); - out0 = _mm_cvtsi32_ss(factor, s0>>8); - out1 = _mm_cvtsi32_ss(factor, s1>>8); - out2 = _mm_cvtsi32_ss(factor, s2>>8); - out3 = _mm_cvtsi32_ss(factor, s3>>8); + __m128 out4, factor = _mm_set1_ps(1.0f / S32_SCALE); + out0 = _mm_cvtsi32_ss(factor, s0); + out1 = _mm_cvtsi32_ss(factor, s1); + out2 = _mm_cvtsi32_ss(factor, s2); + out3 = _mm_cvtsi32_ss(factor, s3); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); out2 = _mm_mul_ss(out2, factor); @@ -430,7 +425,7 @@ float *d0 = dst0, *d1 = dst1; uint32_t n, unrolled; __m256i in4, t4; - __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE); + __m256 out4, factor = _mm256_set1_ps(1.0f / S32_SCALE); __m256i perm = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7); __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels); __m256i mask2 = _mm256_setr_epi64x(4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels); @@ -445,9 +440,6 @@ in0 = _mm256_i64gather_epi64((long long int *)s, mask1, 4); in1 = _mm256_i64gather_epi64((long long int *)s, mask2, 4); - in0 = _mm256_srai_epi32(in0, 8); - in1 = _mm256_srai_epi32(in1, 8); - t0 = _mm256_permutevar8x32_epi32(in0, perm); t1 = _mm256_permutevar8x32_epi32(in1, perm); @@ -466,9 +458,9 @@ s += 8*n_channels; } for(; n < n_samples; n++) { - __m128 out2, factor = _mm_set1_ps(1.0f / S24_SCALE); - out0 = _mm_cvtsi32_ss(factor, s0>>8); - out1 = _mm_cvtsi32_ss(factor, s1>>8); + __m128 out2, factor = _mm_set1_ps(1.0f / S32_SCALE); + out0 = _mm_cvtsi32_ss(factor, s0); + out1 = _mm_cvtsi32_ss(factor, s1); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); _mm_store_ss(&d0n, out0); @@ -485,7 +477,7 @@ float *d0 = dst0; uint32_t n, unrolled; __m256i in2; - __m256 out2, factor = _mm256_set1_ps(1.0f / S24_SCALE); + __m256 out2, factor = _mm256_set1_ps(1.0f / S32_SCALE); __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels); __m256i mask2 = _mm256_setr_epi64x(4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels); @@ -502,9 +494,6 @@ _mm256_i64gather_epi32(&s 8*n_channels, mask1, 4), _mm256_i64gather_epi32(&s 8*n_channels, mask2, 4)); - in0 = _mm256_srai_epi32(in0, 8); - in1 = _mm256_srai_epi32(in1, 8); - out0 = _mm256_cvtepi32_ps(in0); out1 = _mm256_cvtepi32_ps(in1); @@ -517,8 +506,8 @@ s += 16*n_channels; } for(; n < n_samples; n++) { - __m128 out, factor = _mm_set1_ps(1.0f / S24_SCALE); - out = _mm_cvtsi32_ss(factor, s0>>8); + __m128 out, factor = _mm_set1_ps(1.0f / S32_SCALE); + out = _mm_cvtsi32_ss(factor, s0); out = _mm_mul_ss(out, factor); _mm_store_ss(&d0n, out); s += n_channels; @@ -560,7 +549,7 @@ for(n = 0; n < unrolled; n += 4) { in0 = _mm_mul_ps(_mm_load_ps(&s0n), scale); in0 = _mm_min_ps(in0, int_max); - out0 = _mm_cvtps_epi32(in0); + out0 = _mm_cvttps_epi32(in0); out1 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(0, 3, 2, 1)); out2 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(1, 0, 3, 2)); out3 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(2, 1, 0, 3)); @@ -605,8 +594,8 @@ in0 = _mm256_min_ps(in0, int_max); in1 = _mm256_min_ps(in1, int_max); - out0 = _mm256_cvtps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - out1 = _mm256_cvtps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ + out0 = _mm256_cvttps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ + out1 = _mm256_cvttps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ t0 = _mm256_unpacklo_epi32(out0, out1); /* a0 b0 a1 b1 a4 b4 a5 b5 */ t1 = _mm256_unpackhi_epi32(out0, out1); /* a2 b2 a3 b3 a6 b6 a7 b7 */ @@ -645,7 +634,7 @@ in0 = _mm_mul_ps(in0, scale); in0 = _mm_min_ps(in0, int_max); - out0 = _mm_cvtps_epi32(in0); + out0 = _mm_cvttps_epi32(in0); _mm_storel_epi64((__m128i*)d, out0); d += n_channels; } @@ -682,10 +671,10 @@ in2 = _mm256_min_ps(in2, int_max); in3 = _mm256_min_ps(in3, int_max); - out0 = _mm256_cvtps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - out1 = _mm256_cvtps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ - out2 = _mm256_cvtps_epi32(in2); /* c0 c1 c2 c3 c4 c5 c6 c7 */ - out3 = _mm256_cvtps_epi32(in3); /* d0 d1 d2 d3 d4 d5 d6 d7 */ + out0 = _mm256_cvttps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ + out1 = _mm256_cvttps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ + out2 = _mm256_cvttps_epi32(in2); /* c0 c1 c2 c3 c4 c5 c6 c7 */ + out3 = _mm256_cvttps_epi32(in3); /* d0 d1 d2 d3 d4 d5 d6 d7 */ t0 = _mm256_unpacklo_epi32(out0, out1); /* a0 b0 a1 b1 a4 b4 a5 b5 */ t1 = _mm256_unpackhi_epi32(out0, out1); /* a2 b2 a3 b3 a6 b6 a7 b7 */ @@ -724,7 +713,7 @@ in0 = _mm_mul_ps(in0, scale); in0 = _mm_min_ps(in0, int_max); - out0 = _mm_cvtps_epi32(in0); + out0 = _mm_cvttps_epi32(in0); _mm_storeu_si128((__m128i*)d, out0); d += n_channels; } @@ -754,8 +743,9 @@ uint32_t n, unrolled; __m128 in2; __m128i out2; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); if (SPA_IS_ALIGNED(s0, 16)) unrolled = n_samples & ~7; @@ -763,10 +753,10 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_max); - in1 = _mm_mul_ps(_mm_load_ps(&s0n+4), int_max); - out0 = _mm_cvtps_epi32(in0); - out1 = _mm_cvtps_epi32(in1); + in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_scale); + in1 = _mm_mul_ps(_mm_load_ps(&s0n+4), int_scale); + out0 = _mm_cvttps_epi32(in0); + out1 = _mm_cvttps_epi32(in1); out0 = _mm_packs_epi32(out0, out1); d0*n_channels = _mm_extract_epi16(out0, 0); @@ -780,7 +770,7 @@ d += 8*n_channels; } for(; n < n_samples; n++) { - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); *d = _mm_cvtss_si32(in0); d += n_channels; @@ -796,7 +786,7 @@ uint32_t n, unrolled; __m256 in2; __m256i out4, t2; - __m256 int_max = _mm256_set1_ps(S16_MAX_F); + __m256 int_scale = _mm256_set1_ps(S16_SCALE); if (SPA_IS_ALIGNED(s0, 32) && SPA_IS_ALIGNED(s1, 32)) @@ -805,11 +795,11 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm256_mul_ps(_mm256_load_ps(&s0n+0), int_max); - in1 = _mm256_mul_ps(_mm256_load_ps(&s1n+0), int_max); + in0 = _mm256_mul_ps(_mm256_load_ps(&s0n+0), int_scale); + in1 = _mm256_mul_ps(_mm256_load_ps(&s1n+0), int_scale); - out0 = _mm256_cvtps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - out1 = _mm256_cvtps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ + out0 = _mm256_cvttps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ + out1 = _mm256_cvttps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ t0 = _mm256_unpacklo_epi32(out0, out1); /* a0 b0 a1 b1 a4 b4 a5 b5 */ t1 = _mm256_unpackhi_epi32(out0, out1); /* a2 b2 a3 b3 a6 b6 a7 b7 */ @@ -829,11 +819,12 @@ } for(; n < n_samples; n++) { __m128 in2; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); - in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); + in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); in1 = _mm_min_ss(int_max, _mm_max_ss(in1, int_min)); d0 = _mm_cvtss_si32(in0); @@ -851,7 +842,7 @@ uint32_t n, unrolled; __m256 in4; __m256i out4, t4; - __m256 int_max = _mm256_set1_ps(S16_MAX_F); + __m256 int_scale = _mm256_set1_ps(S16_SCALE); if (SPA_IS_ALIGNED(s0, 32) && SPA_IS_ALIGNED(s1, 32) && @@ -862,15 +853,15 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm256_mul_ps(_mm256_load_ps(&s0n), int_max); - in1 = _mm256_mul_ps(_mm256_load_ps(&s1n), int_max); - in2 = _mm256_mul_ps(_mm256_load_ps(&s2n), int_max); - in3 = _mm256_mul_ps(_mm256_load_ps(&s3n), int_max); + in0 = _mm256_mul_ps(_mm256_load_ps(&s0n), int_scale); + in1 = _mm256_mul_ps(_mm256_load_ps(&s1n), int_scale); + in2 = _mm256_mul_ps(_mm256_load_ps(&s2n), int_scale); + in3 = _mm256_mul_ps(_mm256_load_ps(&s3n), int_scale); - t0 = _mm256_cvtps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - t1 = _mm256_cvtps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ - t2 = _mm256_cvtps_epi32(in2); /* c0 c1 c2 c3 c4 c5 c6 c7 */ - t3 = _mm256_cvtps_epi32(in3); /* d0 d1 d2 d3 d4 d5 d6 d7 */ + t0 = _mm256_cvttps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ + t1 = _mm256_cvttps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ + t2 = _mm256_cvttps_epi32(in2); /* c0 c1 c2 c3 c4 c5 c6 c7 */ + t3 = _mm256_cvttps_epi32(in3); /* d0 d1 d2 d3 d4 d5 d6 d7 */ t0 = _mm256_packs_epi32(t0, t2); /* a0 a1 a2 a3 c0 c1 c2 c3 a4 a5 a6 a7 c4 c5 c6 c7 */ t1 = _mm256_packs_epi32(t1, t3); /* b0 b1 b2 b3 d0 d1 d2 d3 b4 b5 b6 b7 d4 d5 d6 d7 */ @@ -905,13 +896,14 @@ } for(; n < n_samples; n++) { __m128 in4; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); - - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); - in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_max); - in2 = _mm_mul_ss(_mm_load_ss(&s2n), int_max); - in3 = _mm_mul_ss(_mm_load_ss(&s3n), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); + + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); + in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_scale); + in2 = _mm_mul_ss(_mm_load_ss(&s2n), int_scale); + in3 = _mm_mul_ss(_mm_load_ss(&s3n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); in1 = _mm_min_ss(int_max, _mm_max_ss(in1, int_min)); in2 = _mm_min_ss(int_max, _mm_max_ss(in2, int_min)); @@ -948,7 +940,7 @@ uint32_t n, unrolled; __m256 in4; __m256i out4, t4; - __m256 int_max = _mm256_set1_ps(S16_MAX_F); + __m256 int_scale = _mm256_set1_ps(S16_SCALE); if (SPA_IS_ALIGNED(s0, 32) && SPA_IS_ALIGNED(s1, 32) && @@ -959,15 +951,15 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm256_mul_ps(_mm256_load_ps(&s0n), int_max); - in1 = _mm256_mul_ps(_mm256_load_ps(&s1n), int_max); - in2 = _mm256_mul_ps(_mm256_load_ps(&s2n), int_max); - in3 = _mm256_mul_ps(_mm256_load_ps(&s3n), int_max); + in0 = _mm256_mul_ps(_mm256_load_ps(&s0n), int_scale); + in1 = _mm256_mul_ps(_mm256_load_ps(&s1n), int_scale); + in2 = _mm256_mul_ps(_mm256_load_ps(&s2n), int_scale); + in3 = _mm256_mul_ps(_mm256_load_ps(&s3n), int_scale); - t0 = _mm256_cvtps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - t1 = _mm256_cvtps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ - t2 = _mm256_cvtps_epi32(in2); /* c0 c1 c2 c3 c4 c5 c6 c7 */ - t3 = _mm256_cvtps_epi32(in3); /* d0 d1 d2 d3 d4 d5 d6 d7 */ + t0 = _mm256_cvttps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ + t1 = _mm256_cvttps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ + t2 = _mm256_cvttps_epi32(in2); /* c0 c1 c2 c3 c4 c5 c6 c7 */ + t3 = _mm256_cvttps_epi32(in3); /* d0 d1 d2 d3 d4 d5 d6 d7 */ t0 = _mm256_packs_epi32(t0, t2); /* a0 a1 a2 a3 c0 c1 c2 c3 a4 a5 a6 a7 c4 c5 c6 c7 */ t1 = _mm256_packs_epi32(t1, t3); /* b0 b1 b2 b3 d0 d1 d2 d3 b4 b5 b6 b7 d4 d5 d6 d7 */ @@ -987,13 +979,14 @@ } for(; n < n_samples; n++) { __m128 in4; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); - - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); - in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_max); - in2 = _mm_mul_ss(_mm_load_ss(&s2n), int_max); - in3 = _mm_mul_ss(_mm_load_ss(&s3n), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); + + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); + in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_scale); + in2 = _mm_mul_ss(_mm_load_ss(&s2n), int_scale); + in3 = _mm_mul_ss(_mm_load_ss(&s3n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); in1 = _mm_min_ss(int_max, _mm_max_ss(in1, int_min)); in2 = _mm_min_ss(int_max, _mm_max_ss(in2, int_min)); @@ -1014,7 +1007,7 @@ uint32_t n, unrolled; __m256 in4; __m256i out4, t4; - __m256 int_max = _mm256_set1_ps(S16_MAX_F); + __m256 int_scale = _mm256_set1_ps(S16_SCALE); if (SPA_IS_ALIGNED(s0, 32) && SPA_IS_ALIGNED(s1, 32)) @@ -1023,15 +1016,15 @@ unrolled = 0; for(n = 0; n < unrolled; n += 16) { - in0 = _mm256_mul_ps(_mm256_load_ps(&s0n+0), int_max); - in1 = _mm256_mul_ps(_mm256_load_ps(&s1n+0), int_max); - in2 = _mm256_mul_ps(_mm256_load_ps(&s0n+8), int_max); - in3 = _mm256_mul_ps(_mm256_load_ps(&s1n+8), int_max); + in0 = _mm256_mul_ps(_mm256_load_ps(&s0n+0), int_scale); + in1 = _mm256_mul_ps(_mm256_load_ps(&s1n+0), int_scale); + in2 = _mm256_mul_ps(_mm256_load_ps(&s0n+8), int_scale); + in3 = _mm256_mul_ps(_mm256_load_ps(&s1n+8), int_scale); - out0 = _mm256_cvtps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - out1 = _mm256_cvtps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ - out2 = _mm256_cvtps_epi32(in2); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - out3 = _mm256_cvtps_epi32(in3); /* b0 b1 b2 b3 b4 b5 b6 b7 */ + out0 = _mm256_cvttps_epi32(in0); /* a0 a1 a2 a3 a4 a5 a6 a7 */ + out1 = _mm256_cvttps_epi32(in1); /* b0 b1 b2 b3 b4 b5 b6 b7 */ + out2 = _mm256_cvttps_epi32(in2); /* a0 a1 a2 a3 a4 a5 a6 a7 */ + out3 = _mm256_cvttps_epi32(in3); /* b0 b1 b2 b3 b4 b5 b6 b7 */ t0 = _mm256_unpacklo_epi32(out0, out1); /* a0 b0 a1 b1 a4 b4 a5 b5 */ t1 = _mm256_unpackhi_epi32(out0, out1); /* a2 b2 a3 b3 a6 b6 a7 b7 */ @@ -1048,11 +1041,12 @@ } for(; n < n_samples; n++) { __m128 in4; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); - in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); + in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); in1 = _mm_min_ss(int_max, _mm_max_ss(in1, int_min)); d0 = _mm_cvtss_si32(in0);
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/fmt-ops-c.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/fmt-ops-c.c
Changed
@@ -33,708 +33,196 @@ #include "fmt-ops.h" #include "law.h" -void -conv_copy8d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - for (i = 0; i < n_channels; i++) - spa_memcpy(dsti, srci, n_samples); -} - -void -conv_copy8_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - spa_memcpy(dst0, src0, n_samples * conv->n_channels); -} - - -void -conv_copy16d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - for (i = 0; i < n_channels; i++) - spa_memcpy(dsti, srci, n_samples * sizeof(int16_t)); -} - -void -conv_copy16_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - spa_memcpy(dst0, src0, n_samples * sizeof(int16_t) * conv->n_channels); -} - -void -conv_copy24d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - for (i = 0; i < n_channels; i++) - spa_memcpy(dsti, srci, n_samples * 3); -} - -void -conv_copy24_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - spa_memcpy(dst0, src0, n_samples * 3 * conv->n_channels); -} - -void -conv_copy32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - for (i = 0; i < n_channels; i++) - spa_memcpy(dsti, srci, n_samples * sizeof(int32_t)); -} - -void -conv_copy32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - spa_memcpy(dst0, src0, n_samples * sizeof(int32_t) * conv->n_channels); -} - -void -conv_copy64d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - for (i = 0; i < n_channels; i++) - spa_memcpy(dsti, srci, n_samples * sizeof(int64_t)); -} - -void -conv_copy64_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - spa_memcpy(dst0, src0, n_samples * sizeof(int64_t) * conv->n_channels); -} - -void -conv_u8d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const uint8_t *s = srci; - float *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = U8_TO_F32(sj); - } -} - -void -conv_u8_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const uint8_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = U8_TO_F32(si); -} - -void -conv_u8_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = U8_TO_F32(*s++); - } -} - -void -conv_u8d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t **s = (const uint8_t **) src; - float *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = U8_TO_F32(sij); - } -} - -void -conv_s8d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const int8_t *s = srci; - float *d = dsti; - for (j = 0; j < n_samples; j++) - dj = S8_TO_F32(sj); - } -} - -void -conv_s8_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const int8_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = S8_TO_F32(si); -} - -void -conv_s8_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int8_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = S8_TO_F32(*s++); - } -} - -void -conv_s8d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int8_t **s = (const int8_t **) src; - float *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = S8_TO_F32(sij); - } -} - -void -conv_alaw_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = alaw_to_f32(*s++); - } -} - -void -conv_ulaw_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = ulaw_to_f32(*s++); - } -} - -void -conv_u16_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const uint16_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = U16_TO_F32(si); -} - -void -conv_u16_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint16_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = U16_TO_F32(*s++); - } -} - -void -conv_s16d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const int16_t *s = srci; - float *d = dsti; - for (j = 0; j < n_samples; j++) - dj = S16_TO_F32(sj); - } -} - -void -conv_s16_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const int16_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = S16_TO_F32(si); -} - -void -conv_s16_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int16_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = S16_TO_F32(*s++); - } -} - -void -conv_s16s_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int16_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = S16S_TO_F32(*s++); - } -} - -void -conv_s16d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int16_t **s = (const int16_t **) src; - float *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = S16_TO_F32(sij); - } -} - -void -conv_u32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const uint32_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = U32_TO_F32(si); -} - -void -conv_u32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint32_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = U32_TO_F32(*s++); - } -} - -void -conv_s32d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const int32_t *s = srci; - float *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = S32_TO_F32(sj); - } -} - -void -conv_s32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const int32_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = S32_TO_F32(si); -} - -void -conv_s32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = S32_TO_F32(*s++); - } -} - -void -conv_s32s_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; +#define MAKE_COPY(size) \ +void conv_copy ##size## d_c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + uint32_t i, n_channels = conv->n_channels; \ + for (i = 0; i < n_channels; i++) \ + spa_memcpy(dsti, srci, n_samples * (size>>3)); \ +} \ +void conv_copy ##size## _c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + spa_memcpy(dst0, src0, n_samples * conv->n_channels * (size>>3)); \ +} + +MAKE_COPY(8); +MAKE_COPY(16); +MAKE_COPY(24); +MAKE_COPY(32); +MAKE_COPY(64); + +#define MAKE_D_TO_D(sname,stype,dname,dtype,func) \ +void conv_ ##sname## d_to_ ##dname## d_c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + uint32_t i, j, n_channels = conv->n_channels; \ + for (i = 0; i < n_channels; i++) { \ + const stype *s = srci; \ + dtype *d = dsti; \ + for (j = 0; j < n_samples; j++) \ + dj = func (sj); \ + } \ +} + +#define MAKE_I_TO_I(sname,stype,dname,dtype,func) \ +void conv_ ##sname## _to_ ##dname## _c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + uint32_t j; \ + const stype *s = src0; \ + dtype *d = dst0; \ + n_samples *= conv->n_channels; \ + for (j = 0; j < n_samples; j++) \ + dj = func (sj); \ +} + +#define MAKE_I_TO_D(sname,stype,dname,dtype,func) \ +void conv_ ##sname## _to_ ##dname## d_c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + const stype *s = src0; \ + dtype **d = (dtype**)dst; \ + uint32_t i, j, n_channels = conv->n_channels; \ + for (j = 0; j < n_samples; j++) { \ + for (i = 0; i < n_channels; i++) \ + dij = func (*s++); \ + } \ +} + +#define MAKE_D_TO_I(sname,stype,dname,dtype,func) \ +void conv_ ##sname## d_to_ ##dname## _c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + const stype **s = (const stype **)src; \ + dtype *d = dst0; \ + uint32_t i, j, n_channels = conv->n_channels; \ + for (j = 0; j < n_samples; j++) { \ + for (i = 0; i < n_channels; i++) \ + *d++ = func (sij); \ + } \ +} + +/* to f32 */ +MAKE_D_TO_D(u8, uint8_t, f32, float, U8_TO_F32); +MAKE_I_TO_I(u8, uint8_t, f32, float, U8_TO_F32); +MAKE_I_TO_D(u8, uint8_t, f32, float, U8_TO_F32); +MAKE_D_TO_I(u8, uint8_t, f32, float, U8_TO_F32); + +MAKE_D_TO_D(s8, int8_t, f32, float, S8_TO_F32); +MAKE_I_TO_I(s8, int8_t, f32, float, S8_TO_F32); +MAKE_I_TO_D(s8, int8_t, f32, float, S8_TO_F32); +MAKE_D_TO_I(s8, int8_t, f32, float, S8_TO_F32); + +MAKE_I_TO_D(alaw, uint8_t, f32, float, alaw_to_f32); +MAKE_I_TO_D(ulaw, uint8_t, f32, float, ulaw_to_f32); + +MAKE_I_TO_I(u16, uint16_t, f32, float, U16_TO_F32); +MAKE_I_TO_D(u16, uint16_t, f32, float, U16_TO_F32); + +MAKE_D_TO_D(s16, int16_t, f32, float, S16_TO_F32); +MAKE_I_TO_I(s16, int16_t, f32, float, S16_TO_F32); +MAKE_I_TO_D(s16, int16_t, f32, float, S16_TO_F32); +MAKE_D_TO_I(s16, int16_t, f32, float, S16_TO_F32); +MAKE_I_TO_D(s16s, uint16_t, f32, float, S16S_TO_F32); + +MAKE_I_TO_I(u32, uint32_t, f32, float, U32_TO_F32); +MAKE_I_TO_D(u32, uint32_t, f32, float, U32_TO_F32); + +MAKE_D_TO_D(s32, int32_t, f32, float, S32_TO_F32); +MAKE_I_TO_I(s32, int32_t, f32, float, S32_TO_F32); +MAKE_I_TO_D(s32, int32_t, f32, float, S32_TO_F32); +MAKE_D_TO_I(s32, int32_t, f32, float, S32_TO_F32); +MAKE_I_TO_D(s32s, uint32_t, f32, float, S32S_TO_F32); + +MAKE_I_TO_I(u24, uint24_t, f32, float, U24_TO_F32); +MAKE_I_TO_D(u24, uint24_t, f32, float, U24_TO_F32); + +MAKE_D_TO_D(s24, int24_t, f32, float, S24_TO_F32); +MAKE_I_TO_I(s24, int24_t, f32, float, S24_TO_F32); +MAKE_I_TO_D(s24, int24_t, f32, float, S24_TO_F32); +MAKE_D_TO_I(s24, int24_t, f32, float, S24_TO_F32); +MAKE_I_TO_D(s24s, int24_t, f32, float, S24S_TO_F32); + +MAKE_I_TO_I(u24_32, uint32_t, f32, float, U24_32_TO_F32); +MAKE_I_TO_D(u24_32, uint32_t, f32, float, U24_32_TO_F32); + +MAKE_D_TO_D(s24_32, int32_t, f32, float, S24_32_TO_F32); +MAKE_I_TO_I(s24_32, int32_t, f32, float, S24_32_TO_F32); +MAKE_I_TO_D(s24_32, int32_t, f32, float, S24_32_TO_F32); +MAKE_D_TO_I(s24_32, int32_t, f32, float, S24_32_TO_F32); +MAKE_I_TO_D(s24_32s, uint32_t, f32, float, S24_32S_TO_F32); + +MAKE_D_TO_D(f64, double, f32, float, (float)); +MAKE_I_TO_I(f64, double, f32, float, (float)); +MAKE_I_TO_D(f64, double, f32, float, (float)); +MAKE_D_TO_I(f64, double, f32, float, (float)); +MAKE_I_TO_D(f64s, double, f32, float, bswap_64); /* FIXME */ + + +/* from f32 */ +MAKE_D_TO_D(f32, float, u8, uint8_t, F32_TO_U8); +MAKE_I_TO_I(f32, float, u8, uint8_t, F32_TO_U8); +MAKE_I_TO_D(f32, float, u8, uint8_t, F32_TO_U8); +MAKE_D_TO_I(f32, float, u8, uint8_t, F32_TO_U8); + +MAKE_D_TO_D(f32, float, s8, int8_t, F32_TO_S8); +MAKE_I_TO_I(f32, float, s8, int8_t, F32_TO_S8); +MAKE_I_TO_D(f32, float, s8, int8_t, F32_TO_S8); +MAKE_D_TO_I(f32, float, s8, int8_t, F32_TO_S8); + +MAKE_D_TO_I(f32, float, alaw, uint8_t, f32_to_alaw); +MAKE_D_TO_I(f32, float, ulaw, uint8_t, f32_to_ulaw); + +MAKE_I_TO_I(f32, float, u16, uint16_t, F32_TO_U16); +MAKE_D_TO_I(f32, float, u16, uint16_t, F32_TO_U16); + +MAKE_D_TO_D(f32, float, s16, int16_t, F32_TO_S16); +MAKE_I_TO_I(f32, float, s16, int16_t, F32_TO_S16); +MAKE_I_TO_D(f32, float, s16, int16_t, F32_TO_S16); +MAKE_D_TO_I(f32, float, s16, int16_t, F32_TO_S16); +MAKE_D_TO_I(f32, float, s16s, uint16_t, F32_TO_S16S); + +MAKE_I_TO_I(f32, float, u32, uint32_t, F32_TO_U32); +MAKE_D_TO_I(f32, float, u32, uint32_t, F32_TO_U32); + +MAKE_D_TO_D(f32, float, s32, int32_t, F32_TO_S32); +MAKE_I_TO_I(f32, float, s32, int32_t, F32_TO_S32); +MAKE_I_TO_D(f32, float, s32, int32_t, F32_TO_S32); +MAKE_D_TO_I(f32, float, s32, int32_t, F32_TO_S32); +MAKE_D_TO_I(f32, float, s32s, uint32_t, F32_TO_S32S); + +MAKE_I_TO_I(f32, float, u24, uint24_t, F32_TO_U24); +MAKE_D_TO_I(f32, float, u24, uint24_t, F32_TO_U24); + +MAKE_D_TO_D(f32, float, s24, int24_t, F32_TO_S24); +MAKE_I_TO_I(f32, float, s24, int24_t, F32_TO_S24); +MAKE_I_TO_D(f32, float, s24, int24_t, F32_TO_S24); +MAKE_D_TO_I(f32, float, s24, int24_t, F32_TO_S24); +MAKE_D_TO_I(f32, float, s24s, int24_t, F32_TO_S24S); + +MAKE_I_TO_I(f32, float, u24_32, uint32_t, F32_TO_U24_32); +MAKE_D_TO_I(f32, float, u24_32, uint32_t, F32_TO_U24_32); + +MAKE_D_TO_D(f32, float, s24_32, int32_t, F32_TO_S24_32); +MAKE_I_TO_I(f32, float, s24_32, int32_t, F32_TO_S24_32); +MAKE_I_TO_D(f32, float, s24_32, int32_t, F32_TO_S24_32); +MAKE_D_TO_I(f32, float, s24_32, int32_t, F32_TO_S24_32); +MAKE_D_TO_I(f32, float, s24_32s, uint32_t, F32_TO_S24_32S); + +MAKE_D_TO_D(f32, float, f64, double, (double)); +MAKE_I_TO_I(f32, float, f64, double, (double)); +MAKE_I_TO_D(f32, float, f64, double, (double)); +MAKE_D_TO_I(f32, float, f64, double, (double)); +MAKE_D_TO_I(f32, float, f64s, double, bswap_32); /* FIXME */ - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = S32S_TO_F32(*s++); - } -} - -void -conv_s32d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t **s = (const int32_t **) src; - float *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = S32_TO_F32(sij); - } -} - -void -conv_u24_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const uint8_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) { - di = U24_TO_F32(read_u24(s)); - s += 3; - } -} - -void -conv_u24_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - dij = U24_TO_F32(read_u24(s)); - s += 3; - } - } -} - -void -conv_s24d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const int8_t *s = srci; - float *d = dsti; - - for (j = 0; j < n_samples; j++) { - dj = S24_TO_F32(read_s24(s)); - s += 3; - } - } -} - -void -conv_s24_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const int8_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) { - di = S24_TO_F32(read_s24(s)); - s += 3; - } -} - -void -conv_s24_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - dij = S24_TO_F32(read_s24(s)); - s += 3; - } - } -} - -void -conv_s24s_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - dij = S24_TO_F32(read_s24s(s)); - s += 3; - } - } -} - -void -conv_s24d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t **s = (const uint8_t **) src; - float *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - *d++ = S24_TO_F32(read_s24(&sij*3)); - } - } -} - -void -conv_u24_32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const uint32_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) { - di = U24_32_TO_F32(si); - } -} - -void -conv_u24_32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint32_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = U24_32_TO_F32(*s++); - } -} - -void -conv_s24_32d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const int32_t *s = srci; - float *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = S24_32_TO_F32(sj); - } -} - -void -conv_s24_32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const int32_t *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) { - di = S24_32_TO_F32(si); - } -} - -void -conv_s24_32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = S24_32_TO_F32(*s++); - } -} - -void -conv_s24_32s_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = S24_32S_TO_F32(*s++); - } -} - -void -conv_s24_32d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t **s = (const int32_t **) src; - float *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = S24_32_TO_F32(sij); - } -} - -void -conv_f64d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const double *s = srci; - float *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = sj; - } -} - -void -conv_f64_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const double *s = src0; - float *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = si; -} - -void -conv_f64_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const double *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = *s++; - } -} - -void -conv_f64s_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const double *s = src0; - float **d = (float **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = bswap_64(*s++); - } -} - -void -conv_f64d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const double **s = (const double **) src; - float *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = sij; - } -} static inline int32_t lcnoise(uint32_t *state) @@ -753,6 +241,62 @@ dithern = lcnoise(state) * scale; } +#define MAKE_D_dither(dname,dtype,func) \ +void conv_f32d_to_ ##dname## d_dither_c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \ + float *dither = conv->dither; \ + update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \ + for (i = 0; i < n_channels; i++) { \ + const float *s = srci; \ + dtype *d = dsti; \ + for (j = 0; j < n_samples;) { \ + chunk = SPA_MIN(n_samples - j, dither_size); \ + for (k = 0; k < chunk; k++, j++) \ + dj = func (sj, ditherk); \ + } \ + } \ +} + +#define MAKE_I_dither(dname,dtype,func) \ +void conv_f32d_to_ ##dname## _dither_c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + const float **s = (const float **) src; \ + dtype *d = dst0; \ + uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \ + float *dither = conv->dither; \ + update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \ + for (j = 0; j < n_samples;) { \ + chunk = SPA_MIN(n_samples - j, dither_size); \ + for (k = 0; k < chunk; k++, j++) { \ + for (i = 0; i < n_channels; i++) \ + *d++ = func (sij, ditherk); \ + } \ + } \ +} + +MAKE_D_dither(u8, uint8_t, F32_TO_U8_D); +MAKE_I_dither(u8, uint8_t, F32_TO_U8_D); +MAKE_D_dither(s8, int8_t, F32_TO_S8_D); +MAKE_I_dither(s8, int8_t, F32_TO_S8_D); +MAKE_D_dither(s16, int16_t, F32_TO_S16_D); +MAKE_I_dither(s16, int16_t, F32_TO_S16_D); +MAKE_I_dither(s16s, uint16_t, F32_TO_S16S_D); +MAKE_D_dither(s32, int32_t, F32_TO_S32_D); +MAKE_I_dither(s32, int32_t, F32_TO_S32_D); +MAKE_I_dither(s32s, uint32_t, F32_TO_S32S_D); +MAKE_D_dither(s24, int24_t, F32_TO_S24_D); +MAKE_I_dither(s24, int24_t, F32_TO_S24_D); +MAKE_I_dither(s24s, int24_t, F32_TO_S24_D); +MAKE_D_dither(s24_32, int32_t, F32_TO_S24_32_D); +MAKE_I_dither(s24_32, int32_t, F32_TO_S24_32_D); +MAKE_I_dither(s24_32s, int32_t, F32_TO_S24_32S_D); + + #define SHAPER5(type,s,scale,offs,sh,min,max,d) \ ({ \ type t; \ @@ -773,1299 +317,75 @@ #define F32_TO_S16_SH(s,sh,d) SHAPER5(int16_t, s, S16_SCALE, 0, sh, S16_MIN, S16_MAX, d) #define F32_TO_S16S_SH(s,sh,d) bswap_16(F32_TO_S16_SH(s,sh,d)) -void -conv_f32d_to_u8d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - uint8_t *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = F32_TO_U8(sj); - } -} - -void -conv_f32d_to_u8d_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - uint8_t *d = dsti; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_U8_D(sj, ditherk); - } - } -} - -void -conv_f32d_to_u8d_shaped_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - uint8_t *d = dsti; - struct shaper *sh = &conv->shaperi; - uint32_t idx = sh->idx; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_U8_SH(sj, sh, ditherk); - } - sh->idx = idx; - } -} - -void -conv_f32_to_u8_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - uint8_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_U8(si); -} - -void -conv_f32_to_u8d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float *s = src0; - uint8_t **d = (uint8_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = F32_TO_U8(*s++); - } -} - -void -conv_f32d_to_u8_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_U8(sij); - } -} - -void -conv_f32d_to_u8_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint8_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_U8_D(sij, ditherk); - } - } -} - -void -conv_f32d_to_u8_shaped_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint8_t *d0 = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - uint8_t *d = &d0i; - struct shaper *sh = &conv->shaperi; - uint32_t idx = sh->idx; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj * n_channels = F32_TO_U8_SH(sj, sh, ditherk); - } - sh->idx = idx; - } -} - -void -conv_f32d_to_s8d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int8_t *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = F32_TO_S8(sj); - } -} - -void -conv_f32d_to_s8d_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int8_t *d = dsti; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_S8_D(sj, ditherk); - } - } -} - -void -conv_f32d_to_s8d_shaped_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int8_t *d = dsti; - struct shaper *sh = &conv->shaperi; - uint32_t idx = sh->idx; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_S8_SH(sj, sh, ditherk); - } - sh->idx = idx; - } -} - -void -conv_f32_to_s8_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - int8_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_S8(si); -} - -void -conv_f32_to_s8d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float *s = src0; - int8_t **d = (int8_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = F32_TO_S8(*s++); - } -} - -void -conv_f32d_to_s8_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S8(sij); - } -} - -void -conv_f32d_to_s8_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int8_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S8_D(sij, ditherk); - } - } -} - -void -conv_f32d_to_s8_shaped_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - int8_t *d0 = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int8_t *d = &d0i; - struct shaper *sh = &conv->shaperi; - uint32_t idx = sh->idx; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj * n_channels = F32_TO_S8_SH(sj, sh, ditherk); - } - sh->idx = idx; - } -} - -void -conv_f32d_to_alaw_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = f32_to_alaw(sij); - } -} - -void -conv_f32d_to_ulaw_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = f32_to_ulaw(sij); - } -} - -void -conv_f32_to_u16_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - uint16_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_U16(si); -} -void -conv_f32d_to_u16_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint16_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_U16(sij); - } -} - -void -conv_f32d_to_s16d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int16_t *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = F32_TO_S16(sj); - } -} - -void -conv_f32d_to_s16d_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int16_t *d = dsti; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_S16_D(sj, ditherk); - } - } -} - - -void -conv_f32d_to_s16d_shaped_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int16_t *d = dsti; - struct shaper *sh = &conv->shaperi; - uint32_t idx = sh->idx; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_S16_SH(sj, sh, ditherk); - } - sh->idx = idx; - } -} - -void -conv_f32_to_s16_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - int16_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_S16(si); -} - -void -conv_f32_to_s16d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float *s = src0; - int16_t **d = (int16_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = F32_TO_S16(*s++); - } -} - -void -conv_f32d_to_s16_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int16_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S16(sij); - } -} - -void -conv_f32d_to_s16_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int16_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S16_D(sij, ditherk); - } - } -} - -void -conv_f32d_to_s16_shaped_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - int16_t *d0 = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int16_t *d = &d0i; - struct shaper *sh = &conv->shaperi; - uint32_t idx = sh->idx; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj * n_channels = F32_TO_S16_SH(sj, sh, ditherk); - } - sh->idx = idx; - } -} - -void -conv_f32d_to_s16s_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int16_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S16S(sij); - } -} - -void -conv_f32d_to_s16s_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint16_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S16S_D(sij, ditherk); - } - } -} - -void -conv_f32d_to_s16s_shaped_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - int16_t *d0 = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int16_t *d = &d0i; - struct shaper *sh = &conv->shaperi; - uint32_t idx = sh->idx; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj * n_channels = F32_TO_S16S_SH(sj, sh, ditherk); - } - sh->idx = idx; - } -} -void -conv_f32_to_u32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - uint32_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_U32(si); -} - -void -conv_f32d_to_u32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_U32(sij); - } -} - -void -conv_f32d_to_s32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int32_t *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = F32_TO_S32(sj); - } -} - -void -conv_f32d_to_s32d_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int32_t *d = dsti; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_S32_D(sj, ditherk); - } - } -} - -void -conv_f32_to_s32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - int32_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_S32(si); -} - -void -conv_f32_to_s32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float *s = src0; - int32_t **d = (int32_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = F32_TO_S32(*s++); - } -} - -void -conv_f32d_to_s32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S32(sij); - } -} - -void -conv_f32d_to_s32_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int32_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S32_D(sij, ditherk); - } - } -} - -void -conv_f32d_to_s32s_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S32S(sij); - } -} - -void -conv_f32d_to_s32s_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint32_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S32S_D(sij, ditherk); - } - } -} - -void -conv_f32d_to_f64d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - double *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = sj; - } -} - -void -conv_f32_to_f64_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - double *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = si; -} - -void -conv_f32_to_f64d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float *s = src0; - double **d = (double **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = *s++; - } -} - -void -conv_f32d_to_f64_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - double *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = sij; - } -} - -void -conv_f32d_to_f64s_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - double *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = bswap_32(sij); - } -} - -void -conv_f32_to_u24_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - uint8_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) { - write_u24(d, F32_TO_U24(si)); - d += 3; - } -} - -void -conv_f32d_to_u24_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - write_u24(d, F32_TO_U24(sij)); - d += 3; - } - } -} - -void -conv_f32d_to_s24d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - uint8_t *d = dsti; - - for (j = 0; j < n_samples; j++) { - write_s24(d, F32_TO_S24(sj)); - d += 3; - } - } -} - -void -conv_f32d_to_s24d_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - uint8_t *d = dsti; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - write_s24(d, F32_TO_S24_D(sj, ditherk)); - d += 3; - } - } - } -} - -void -conv_f32_to_s24_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - uint8_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) { - write_s24(d, F32_TO_S24(si)); - d += 3; - } -} - -void -conv_f32_to_s24d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float *s = src0; - uint8_t **d = (uint8_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - write_s24(&dij*3, F32_TO_S24(*s++)); - } - } -} - -void -conv_f32d_to_s24_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - write_s24(d, F32_TO_S24(sij)); - d += 3; - } - } -} - -void -conv_f32d_to_s24_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint8_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) { - write_s24(d, F32_TO_S24_D(sij, ditherk)); - d += 3; - } - } - } -} - -void -conv_f32d_to_s24s_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - write_s24s(d, F32_TO_S24(sij)); - d += 3; - } - } -} - -void -conv_f32d_to_s24s_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint8_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) { - write_s24s(d, F32_TO_S24_D(sij, ditherk)); - d += 3; - } - } - } -} - -void -conv_f32d_to_s24_32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, n_channels = conv->n_channels; - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int32_t *d = dsti; - - for (j = 0; j < n_samples; j++) - dj = F32_TO_S24_32(sj); - } -} - -void -conv_f32d_to_s24_32d_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (i = 0; i < n_channels; i++) { - const float *s = srci; - int32_t *d = dsti; - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) - dj = F32_TO_S24_32_D(sj, ditherk); - } - } -} - -void -conv_f32_to_u24_32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - uint32_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_U24_32(si); -} - -void -conv_f32d_to_u24_32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - uint32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_U24_32(sij); - } -} - -void -conv_f32_to_s24_32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - uint32_t i, n_channels = conv->n_channels; - const float *s = src0; - int32_t *d = dst0; - - n_samples *= n_channels; - - for (i = 0; i < n_samples; i++) - di = F32_TO_S24_32(si); -} - -void -conv_f32_to_s24_32d_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float *s = src0; - int32_t **d = (int32_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = F32_TO_S24_32(*s++); - } -} - -void -conv_f32d_to_s24_32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S24_32(sij); - } -} - -void -conv_f32d_to_s24_32_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int32_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S24_32_D(sij, ditherk); - } - } -} - -void -conv_f32d_to_s24_32s_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S24_32S(sij); - } -} - -void -conv_f32d_to_s24_32s_dither_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const float **s = (const float **) src; - int32_t *d = dst0; - uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; - float *dither = conv->dither; - - update_dither_c(conv, SPA_MIN(n_samples, dither_size)); - - for (j = 0; j < n_samples;) { - chunk = SPA_MIN(n_samples - j, dither_size); - for (k = 0; k < chunk; k++, j++) { - for (i = 0; i < n_channels; i++) - *d++ = F32_TO_S24_32S_D(sij, ditherk); - } - } -} - -void -conv_deinterleave_8_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - uint8_t **d = (uint8_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = *s++; - } -} - -void -conv_deinterleave_16_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint16_t *s = src0; - uint16_t **d = (uint16_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = *s++; - } -} - -void -conv_deinterleave_24_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint8_t *s = src0; - uint8_t **d = (uint8_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - write_s24(&dij*3, read_s24(s)); - s += 3; - } - } -} - -void -conv_deinterleave_32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint32_t *s = src0; - uint32_t **d = (uint32_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = *s++; - } -} - -void -conv_deinterleave_32s_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint32_t *s = src0; - uint32_t **d = (uint32_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = bswap_32(*s++); - } -} - -void -conv_deinterleave_64_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const uint64_t *s = src0; - uint64_t **d = (uint64_t **) dst; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - dij = *s++; - } -} - -void -conv_interleave_8_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int8_t **s = (const int8_t **) src; - uint8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = sij; - } -} - -void -conv_interleave_16_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int16_t **s = (const int16_t **) src; - uint16_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = sij; - } -} - -void -conv_interleave_24_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int8_t **s = (const int8_t **) src; - uint8_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) { - write_s24(d, read_s24(&sij*3)); - d += 3; - } - } -} - -void -conv_interleave_32_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t **s = (const int32_t **) src; - uint32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = sij; - } -} - -void -conv_interleave_32s_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int32_t **s = (const int32_t **) src; - uint32_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = bswap_32(sij); - } -} - -void -conv_interleave_64_c(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, - uint32_t n_samples) -{ - const int64_t **s = (const int64_t **) src; - uint64_t *d = dst0; - uint32_t i, j, n_channels = conv->n_channels; - - for (j = 0; j < n_samples; j++) { - for (i = 0; i < n_channels; i++) - *d++ = sij; - } -} +#define MAKE_D_shaped(dname,dtype,func) \ +void conv_f32d_to_ ##dname## d_shaped_c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \ + float *dither = conv->dither; \ + update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \ + for (i = 0; i < n_channels; i++) { \ + const float *s = srci; \ + dtype *d = dsti; \ + struct shaper *sh = &conv->shaperi; \ + uint32_t idx = sh->idx; \ + for (j = 0; j < n_samples;) { \ + chunk = SPA_MIN(n_samples - j, dither_size); \ + for (k = 0; k < chunk; k++, j++) \ + dj = func (sj, sh, ditherk); \ + } \ + sh->idx = idx; \ + } \ +} + +#define MAKE_I_shaped(dname,dtype,func) \ +void conv_f32d_to_ ##dname## _shaped_c(struct convert *conv, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ + uint32_t n_samples) \ +{ \ + dtype *d0 = dst0; \ + uint32_t i, j, k, chunk, n_channels = conv->n_channels, dither_size = conv->dither_size; \ + float *dither = conv->dither; \ + update_dither_c(conv, SPA_MIN(n_samples, dither_size)); \ + for (i = 0; i < n_channels; i++) { \ + const float *s = srci; \ + dtype *d = &d0i; \ + struct shaper *sh = &conv->shaperi; \ + uint32_t idx = sh->idx; \ + for (j = 0; j < n_samples;) { \ + chunk = SPA_MIN(n_samples - j, dither_size); \ + for (k = 0; k < chunk; k++, j++) \ + dj*n_channels = func (sj, sh, ditherk); \ + } \ + sh->idx = idx; \ + } \ +} + +MAKE_D_shaped(u8, uint8_t, F32_TO_U8_SH); +MAKE_I_shaped(u8, uint8_t, F32_TO_U8_SH); +MAKE_D_shaped(s8, int8_t, F32_TO_S8_SH); +MAKE_I_shaped(s8, int8_t, F32_TO_S8_SH); +MAKE_D_shaped(s16, int16_t, F32_TO_S16_SH); +MAKE_I_shaped(s16, int16_t, F32_TO_S16_SH); +MAKE_I_shaped(s16s, uint16_t, F32_TO_S16S_SH); + +#define MAKE_DEINTERLEAVE(size,type,func) \ + MAKE_I_TO_D(size,type,size,type,func) + +MAKE_DEINTERLEAVE(8, uint8_t, (uint8_t)); +MAKE_DEINTERLEAVE(16, uint16_t, (uint16_t)); +MAKE_DEINTERLEAVE(24, uint24_t, (uint24_t)); +MAKE_DEINTERLEAVE(32, uint32_t, (uint32_t)); +MAKE_DEINTERLEAVE(32s, uint32_t, bswap_32); +MAKE_DEINTERLEAVE(64, uint64_t, (uint64_t)); + +#define MAKE_INTERLEAVE(size,type,func) \ + MAKE_D_TO_I(size,type,size,type,func) + +MAKE_INTERLEAVE(8, uint8_t, (uint8_t)); +MAKE_INTERLEAVE(16, uint16_t, (uint16_t)); +MAKE_INTERLEAVE(24, uint24_t, (uint24_t)); +MAKE_INTERLEAVE(32, uint32_t, (uint32_t)); +MAKE_INTERLEAVE(32s, uint32_t, bswap_32); +MAKE_INTERLEAVE(64, uint64_t, (uint64_t));
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/fmt-ops-sse2.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/fmt-ops-sse2.c
Changed
@@ -132,7 +132,7 @@ conv_s24_to_f32d_1s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0; uint32_t n, unrolled; __m128i in; @@ -149,21 +149,21 @@ for(n = 0; n < unrolled; n += 4) { in = _mm_setr_epi32( *((uint32_t*)&s0 * n_channels), - *((uint32_t*)&s3 * n_channels), - *((uint32_t*)&s6 * n_channels), - *((uint32_t*)&s9 * n_channels)); + *((uint32_t*)&s1 * n_channels), + *((uint32_t*)&s2 * n_channels), + *((uint32_t*)&s3 * n_channels)); in = _mm_slli_epi32(in, 8); in = _mm_srai_epi32(in, 8); out = _mm_cvtepi32_ps(in); out = _mm_mul_ps(out, factor); _mm_store_ps(&d0n, out); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out = _mm_cvtsi32_ss(factor, read_s24(s)); + out = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); out = _mm_mul_ss(out, factor); _mm_store_ss(&d0n, out); - s += 3 * n_channels; + s += n_channels; } } @@ -171,7 +171,7 @@ conv_s24_to_f32d_2s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0, *d1 = dst1; uint32_t n, unrolled; __m128i in2; @@ -190,14 +190,14 @@ for(n = 0; n < unrolled; n += 4) { in0 = _mm_setr_epi32( *((uint32_t*)&s0 + 0*n_channels), - *((uint32_t*)&s0 + 3*n_channels), - *((uint32_t*)&s0 + 6*n_channels), - *((uint32_t*)&s0 + 9*n_channels)); + *((uint32_t*)&s0 + 1*n_channels), + *((uint32_t*)&s0 + 2*n_channels), + *((uint32_t*)&s0 + 3*n_channels)); in1 = _mm_setr_epi32( - *((uint32_t*)&s3 + 0*n_channels), - *((uint32_t*)&s3 + 3*n_channels), - *((uint32_t*)&s3 + 6*n_channels), - *((uint32_t*)&s3 + 9*n_channels)); + *((uint32_t*)&s1 + 0*n_channels), + *((uint32_t*)&s1 + 1*n_channels), + *((uint32_t*)&s1 + 2*n_channels), + *((uint32_t*)&s1 + 3*n_channels)); in0 = _mm_slli_epi32(in0, 8); in1 = _mm_slli_epi32(in1, 8); @@ -214,23 +214,23 @@ _mm_store_ps(&d0n, out0); _mm_store_ps(&d1n, out1); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out0 = _mm_cvtsi32_ss(factor, read_s24(s)); - out1 = _mm_cvtsi32_ss(factor, read_s24(s+3)); + out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); + out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+1))); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); _mm_store_ss(&d0n, out0); _mm_store_ss(&d1n, out1); - s += 3 * n_channels; + s += n_channels; } } static void conv_s24_to_f32d_4s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0, *d1 = dst1, *d2 = dst2, *d3 = dst3; uint32_t n, unrolled; __m128i in4; @@ -251,24 +251,24 @@ for(n = 0; n < unrolled; n += 4) { in0 = _mm_setr_epi32( *((uint32_t*)&s0 + 0*n_channels), - *((uint32_t*)&s0 + 3*n_channels), - *((uint32_t*)&s0 + 6*n_channels), - *((uint32_t*)&s0 + 9*n_channels)); + *((uint32_t*)&s0 + 1*n_channels), + *((uint32_t*)&s0 + 2*n_channels), + *((uint32_t*)&s0 + 3*n_channels)); in1 = _mm_setr_epi32( - *((uint32_t*)&s3 + 0*n_channels), - *((uint32_t*)&s3 + 3*n_channels), - *((uint32_t*)&s3 + 6*n_channels), - *((uint32_t*)&s3 + 9*n_channels)); + *((uint32_t*)&s1 + 0*n_channels), + *((uint32_t*)&s1 + 1*n_channels), + *((uint32_t*)&s1 + 2*n_channels), + *((uint32_t*)&s1 + 3*n_channels)); in2 = _mm_setr_epi32( - *((uint32_t*)&s6 + 0*n_channels), - *((uint32_t*)&s6 + 3*n_channels), - *((uint32_t*)&s6 + 6*n_channels), - *((uint32_t*)&s6 + 9*n_channels)); + *((uint32_t*)&s2 + 0*n_channels), + *((uint32_t*)&s2 + 1*n_channels), + *((uint32_t*)&s2 + 2*n_channels), + *((uint32_t*)&s2 + 3*n_channels)); in3 = _mm_setr_epi32( - *((uint32_t*)&s9 + 0*n_channels), - *((uint32_t*)&s9 + 3*n_channels), - *((uint32_t*)&s9 + 6*n_channels), - *((uint32_t*)&s9 + 9*n_channels)); + *((uint32_t*)&s3 + 0*n_channels), + *((uint32_t*)&s3 + 1*n_channels), + *((uint32_t*)&s3 + 2*n_channels), + *((uint32_t*)&s3 + 3*n_channels)); in0 = _mm_slli_epi32(in0, 8); in1 = _mm_slli_epi32(in1, 8); @@ -295,13 +295,13 @@ _mm_store_ps(&d2n, out2); _mm_store_ps(&d3n, out3); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out0 = _mm_cvtsi32_ss(factor, read_s24(s)); - out1 = _mm_cvtsi32_ss(factor, read_s24(s+3)); - out2 = _mm_cvtsi32_ss(factor, read_s24(s+6)); - out3 = _mm_cvtsi32_ss(factor, read_s24(s+9)); + out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); + out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+1))); + out2 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+2))); + out3 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+3))); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); out2 = _mm_mul_ss(out2, factor); @@ -310,7 +310,7 @@ _mm_store_ss(&d1n, out1); _mm_store_ss(&d2n, out2); _mm_store_ss(&d3n, out3); - s += 3 * n_channels; + s += n_channels; } } @@ -338,7 +338,7 @@ float *d0 = dst0; uint32_t n, unrolled; __m128i in; - __m128 out, factor = _mm_set1_ps(1.0f / S24_SCALE); + __m128 out, factor = _mm_set1_ps(1.0f / S32_SCALE); if (SPA_IS_ALIGNED(d0, 16)) unrolled = n_samples & ~3; @@ -350,14 +350,13 @@ s1*n_channels, s2*n_channels, s3*n_channels); - in = _mm_srai_epi32(in, 8); out = _mm_cvtepi32_ps(in); out = _mm_mul_ps(out, factor); _mm_store_ps(&d0n, out); s += 4*n_channels; } for(; n < n_samples; n++) { - out = _mm_cvtsi32_ss(factor, s0>>8); + out = _mm_cvtsi32_ss(factor, s0); out = _mm_mul_ss(out, factor); _mm_store_ss(&d0n, out); s += n_channels; @@ -395,7 +394,7 @@ for(n = 0; n < unrolled; n += 4) { in0 = _mm_mul_ps(_mm_load_ps(&s0n), scale); in0 = _mm_min_ps(in0, int_max); - out0 = _mm_cvtps_epi32(in0); + out0 = _mm_cvttps_epi32(in0); out1 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(0, 3, 2, 1)); out2 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(1, 0, 3, 2)); out3 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(2, 1, 0, 3)); @@ -440,8 +439,8 @@ in0 = _mm_min_ps(in0, int_max); in1 = _mm_min_ps(in1, int_max); - out0 = _mm_cvtps_epi32(in0); - out1 = _mm_cvtps_epi32(in1); + out0 = _mm_cvttps_epi32(in0); + out1 = _mm_cvttps_epi32(in1); t0 = _mm_unpacklo_epi32(out0, out1); t1 = _mm_unpackhi_epi32(out0, out1); @@ -460,7 +459,7 @@ in0 = _mm_mul_ps(in0, scale); in0 = _mm_min_ps(in0, int_max); - out0 = _mm_cvtps_epi32(in0); + out0 = _mm_cvttps_epi32(in0); _mm_storel_epi64((__m128i*)d, out0); d += n_channels; } @@ -499,10 +498,10 @@ _MM_TRANSPOSE4_PS(in0, in1, in2, in3); - out0 = _mm_cvtps_epi32(in0); - out1 = _mm_cvtps_epi32(in1); - out2 = _mm_cvtps_epi32(in2); - out3 = _mm_cvtps_epi32(in3); + out0 = _mm_cvttps_epi32(in0); + out1 = _mm_cvttps_epi32(in1); + out2 = _mm_cvttps_epi32(in2); + out3 = _mm_cvttps_epi32(in3); _mm_storeu_si128((__m128i*)(d + 0*n_channels), out0); _mm_storeu_si128((__m128i*)(d + 1*n_channels), out1); @@ -522,7 +521,7 @@ in0 = _mm_mul_ps(in0, scale); in0 = _mm_min_ps(in0, int_max); - out0 = _mm_cvtps_epi32(in0); + out0 = _mm_cvttps_epi32(in0); _mm_storeu_si128((__m128i*)d, out0); d += n_channels; } @@ -590,7 +589,7 @@ in0 = _mm_mul_ps(_mm_load_ps(&sn), scale); in0 = _mm_add_ps(in0, _mm_load_ps(&dithern)); in0 = _mm_min_ps(in0, int_max); - out0 = _mm_cvtps_epi32(in0); + out0 = _mm_cvttps_epi32(in0); out1 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(0, 3, 2, 1)); out2 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(1, 0, 3, 2)); out3 = _mm_shuffle_epi32(out0, _MM_SHUFFLE(2, 1, 0, 3)); @@ -699,7 +698,7 @@ } void -conv_interleave_32_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, +conv_32d_to_32_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_samples) { int32_t *d = dst0; @@ -797,7 +796,7 @@ } void -conv_interleave_32s_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, +conv_32sd_to_32s_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_samples) { int32_t *d = dst0; @@ -878,7 +877,7 @@ } void -conv_deinterleave_32_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, +conv_32_to_32d_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_samples) { const float *s = src0; @@ -965,7 +964,7 @@ } void -conv_deinterleave_32s_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, +conv_32s_to_32sd_sse2(struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_samples) { const float *s = src0; @@ -986,8 +985,9 @@ uint32_t n, unrolled; __m128 in2; __m128i out2; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); if (SPA_IS_ALIGNED(s, 16)) unrolled = n_samples & ~7; @@ -995,16 +995,16 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm_mul_ps(_mm_load_ps(&sn), int_max); - in1 = _mm_mul_ps(_mm_load_ps(&sn+4), int_max); - out0 = _mm_cvtps_epi32(in0); - out1 = _mm_cvtps_epi32(in1); + in0 = _mm_mul_ps(_mm_load_ps(&sn), int_scale); + in1 = _mm_mul_ps(_mm_load_ps(&sn+4), int_scale); + out0 = _mm_cvttps_epi32(in0); + out1 = _mm_cvttps_epi32(in1); out0 = _mm_packs_epi32(out0, out1); _mm_storeu_si128((__m128i*)(d+0), out0); d += 8; } for(; n < n_samples; n++) { - in0 = _mm_mul_ss(_mm_load_ss(&sn), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&sn), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); *d++ = _mm_cvtss_si32(in0); } @@ -1035,8 +1035,9 @@ uint32_t n, unrolled; __m128 in2; __m128i out2; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); if (SPA_IS_ALIGNED(s0, 16)) unrolled = n_samples & ~7; @@ -1044,10 +1045,10 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_max); - in1 = _mm_mul_ps(_mm_load_ps(&s0n+4), int_max); - out0 = _mm_cvtps_epi32(in0); - out1 = _mm_cvtps_epi32(in1); + in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_scale); + in1 = _mm_mul_ps(_mm_load_ps(&s0n+4), int_scale); + out0 = _mm_cvttps_epi32(in0); + out1 = _mm_cvttps_epi32(in1); out0 = _mm_packs_epi32(out0, out1); d0*n_channels = _mm_extract_epi16(out0, 0); @@ -1061,9 +1062,9 @@ d += 8*n_channels; } for(; n < n_samples; n++) { - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); - *d = _mm_cvtss_si32(in0); + *d = _mm_cvttss_si32(in0); d += n_channels; } } @@ -1077,8 +1078,9 @@ uint32_t n, unrolled; __m128 in2; __m128i out4, t2; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); if (SPA_IS_ALIGNED(s0, 16) && SPA_IS_ALIGNED(s1, 16)) @@ -1087,11 +1089,11 @@ unrolled = 0; for(n = 0; n < unrolled; n += 4) { - in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_max); - in1 = _mm_mul_ps(_mm_load_ps(&s1n), int_max); + in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_scale); + in1 = _mm_mul_ps(_mm_load_ps(&s1n), int_scale); - t0 = _mm_cvtps_epi32(in0); - t1 = _mm_cvtps_epi32(in1); + t0 = _mm_cvttps_epi32(in0); + t1 = _mm_cvttps_epi32(in1); t0 = _mm_packs_epi32(t0, t0); t1 = _mm_packs_epi32(t1, t1); @@ -1108,8 +1110,8 @@ d += 4*n_channels; } for(; n < n_samples; n++) { - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); - in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); + in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); in1 = _mm_min_ss(int_max, _mm_max_ss(in1, int_min)); d0 = _mm_cvtss_si32(in0); @@ -1127,8 +1129,9 @@ uint32_t n, unrolled; __m128 in4; __m128i out4, t4; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); if (SPA_IS_ALIGNED(s0, 16) && SPA_IS_ALIGNED(s1, 16) && @@ -1139,15 +1142,15 @@ unrolled = 0; for(n = 0; n < unrolled; n += 4) { - in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_max); - in1 = _mm_mul_ps(_mm_load_ps(&s1n), int_max); - in2 = _mm_mul_ps(_mm_load_ps(&s2n), int_max); - in3 = _mm_mul_ps(_mm_load_ps(&s3n), int_max); + in0 = _mm_mul_ps(_mm_load_ps(&s0n), int_scale); + in1 = _mm_mul_ps(_mm_load_ps(&s1n), int_scale); + in2 = _mm_mul_ps(_mm_load_ps(&s2n), int_scale); + in3 = _mm_mul_ps(_mm_load_ps(&s3n), int_scale); - t0 = _mm_cvtps_epi32(in0); - t1 = _mm_cvtps_epi32(in1); - t2 = _mm_cvtps_epi32(in2); - t3 = _mm_cvtps_epi32(in3); + t0 = _mm_cvttps_epi32(in0); + t1 = _mm_cvttps_epi32(in1); + t2 = _mm_cvttps_epi32(in2); + t3 = _mm_cvttps_epi32(in3); t0 = _mm_packs_epi32(t0, t2); t1 = _mm_packs_epi32(t1, t3); @@ -1165,10 +1168,10 @@ d += 4*n_channels; } for(; n < n_samples; n++) { - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); - in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_max); - in2 = _mm_mul_ss(_mm_load_ss(&s2n), int_max); - in3 = _mm_mul_ss(_mm_load_ss(&s3n), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); + in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_scale); + in2 = _mm_mul_ss(_mm_load_ss(&s2n), int_scale); + in3 = _mm_mul_ss(_mm_load_ss(&s3n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); in1 = _mm_min_ss(int_max, _mm_max_ss(in1, int_min)); in2 = _mm_min_ss(int_max, _mm_max_ss(in2, int_min)); @@ -1205,8 +1208,9 @@ uint32_t n, unrolled; __m128 in4; __m128i out4; - __m128 int_max = _mm_set1_ps(S16_MAX_F); - __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 int_scale = _mm_set1_ps(S16_SCALE); + __m128 int_max = _mm_set1_ps(S16_MAX); + __m128 int_min = _mm_set1_ps(S16_MIN); if (SPA_IS_ALIGNED(s0, 16) && SPA_IS_ALIGNED(s1, 16)) @@ -1215,15 +1219,15 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm_mul_ps(_mm_load_ps(&s0n+0), int_max); - in1 = _mm_mul_ps(_mm_load_ps(&s1n+0), int_max); - in2 = _mm_mul_ps(_mm_load_ps(&s0n+4), int_max); - in3 = _mm_mul_ps(_mm_load_ps(&s1n+4), int_max); + in0 = _mm_mul_ps(_mm_load_ps(&s0n+0), int_scale); + in1 = _mm_mul_ps(_mm_load_ps(&s1n+0), int_scale); + in2 = _mm_mul_ps(_mm_load_ps(&s0n+4), int_scale); + in3 = _mm_mul_ps(_mm_load_ps(&s1n+4), int_scale); - out0 = _mm_cvtps_epi32(in0); - out1 = _mm_cvtps_epi32(in1); - out2 = _mm_cvtps_epi32(in2); - out3 = _mm_cvtps_epi32(in3); + out0 = _mm_cvttps_epi32(in0); + out1 = _mm_cvttps_epi32(in1); + out2 = _mm_cvttps_epi32(in2); + out3 = _mm_cvttps_epi32(in3); out0 = _mm_packs_epi32(out0, out2); out1 = _mm_packs_epi32(out1, out3); @@ -1237,8 +1241,8 @@ d += 16; } for(; n < n_samples; n++) { - in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_max); - in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_max); + in0 = _mm_mul_ss(_mm_load_ss(&s0n), int_scale); + in1 = _mm_mul_ss(_mm_load_ss(&s1n), int_scale); in0 = _mm_min_ss(int_max, _mm_max_ss(in0, int_min)); in1 = _mm_min_ss(int_max, _mm_max_ss(in1, int_min)); d0 = _mm_cvtss_si32(in0);
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/fmt-ops-sse41.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/fmt-ops-sse41.c
Changed
@@ -30,7 +30,7 @@ conv_s24_to_f32d_1s_sse41(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0; uint32_t n, unrolled; __m128i in = _mm_setzero_si128(); @@ -43,21 +43,21 @@ for(n = 0; n < unrolled; n += 4) { in = _mm_insert_epi32(in, *((uint32_t*)&s0 * n_channels), 0); - in = _mm_insert_epi32(in, *((uint32_t*)&s3 * n_channels), 1); - in = _mm_insert_epi32(in, *((uint32_t*)&s6 * n_channels), 2); - in = _mm_insert_epi32(in, *((uint32_t*)&s9 * n_channels), 3); + in = _mm_insert_epi32(in, *((uint32_t*)&s1 * n_channels), 1); + in = _mm_insert_epi32(in, *((uint32_t*)&s2 * n_channels), 2); + in = _mm_insert_epi32(in, *((uint32_t*)&s3 * n_channels), 3); in = _mm_slli_epi32(in, 8); in = _mm_srai_epi32(in, 8); out = _mm_cvtepi32_ps(in); out = _mm_mul_ps(out, factor); _mm_store_ps(&d0n, out); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out = _mm_cvtsi32_ss(factor, read_s24(s)); + out = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); out = _mm_mul_ss(out, factor); _mm_store_ss(&d0n, out); - s += 3 * n_channels; + s += n_channels; } }
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/fmt-ops-ssse3.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/fmt-ops-ssse3.c
Changed
@@ -30,7 +30,7 @@ conv_s24_to_f32d_4s_ssse3(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const uint8_t *s = src; + const int24_t *s = src; float *d0 = dst0, *d1 = dst1, *d2 = dst2, *d3 = dst3; uint32_t n, unrolled; __m128i in4; @@ -48,9 +48,9 @@ for(n = 0; n < unrolled; n += 4) { in0 = _mm_loadu_si128((__m128i*)(s + 0*n_channels)); - in1 = _mm_loadu_si128((__m128i*)(s + 3*n_channels)); - in2 = _mm_loadu_si128((__m128i*)(s + 6*n_channels)); - in3 = _mm_loadu_si128((__m128i*)(s + 9*n_channels)); + in1 = _mm_loadu_si128((__m128i*)(s + 1*n_channels)); + in2 = _mm_loadu_si128((__m128i*)(s + 2*n_channels)); + in3 = _mm_loadu_si128((__m128i*)(s + 3*n_channels)); in0 = _mm_shuffle_epi8(in0, mask); in1 = _mm_shuffle_epi8(in1, mask); in2 = _mm_shuffle_epi8(in2, mask); @@ -74,13 +74,13 @@ _mm_store_ps(&d1n, out1); _mm_store_ps(&d2n, out2); _mm_store_ps(&d3n, out3); - s += 12 * n_channels; + s += 4 * n_channels; } for(; n < n_samples; n++) { - out0 = _mm_cvtsi32_ss(factor, read_s24(s)); - out1 = _mm_cvtsi32_ss(factor, read_s24(s+3)); - out2 = _mm_cvtsi32_ss(factor, read_s24(s+6)); - out3 = _mm_cvtsi32_ss(factor, read_s24(s+9)); + out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); + out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+1))); + out2 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+2))); + out3 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+3))); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); out2 = _mm_mul_ss(out2, factor); @@ -89,7 +89,7 @@ _mm_store_ss(&d1n, out1); _mm_store_ss(&d2n, out2); _mm_store_ss(&d3n, out3); - s += 3 * n_channels; + s += n_channels; } }
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/fmt-ops.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/fmt-ops.c
Changed
@@ -96,22 +96,22 @@ MAKE(F32, F32, 0, conv_copy32_c), MAKE(F32P, F32P, 0, conv_copy32d_c), #if defined (HAVE_SSE2) - MAKE(F32, F32P, 0, conv_deinterleave_32_sse2, SPA_CPU_FLAG_SSE2), + MAKE(F32, F32P, 0, conv_32_to_32d_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(F32, F32P, 0, conv_deinterleave_32_c), + MAKE(F32, F32P, 0, conv_32_to_32d_c), #if defined (HAVE_SSE2) - MAKE(F32P, F32, 0, conv_interleave_32_sse2, SPA_CPU_FLAG_SSE2), + MAKE(F32P, F32, 0, conv_32d_to_32_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(F32P, F32, 0, conv_interleave_32_c), + MAKE(F32P, F32, 0, conv_32d_to_32_c), #if defined (HAVE_SSE2) - MAKE(F32_OE, F32P, 0, conv_deinterleave_32s_sse2, SPA_CPU_FLAG_SSE2), + MAKE(F32_OE, F32P, 0, conv_32s_to_32sd_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(F32_OE, F32P, 0, conv_deinterleave_32s_c), + MAKE(F32_OE, F32P, 0, conv_32s_to_32sd_c), #if defined (HAVE_SSE2) - MAKE(F32P, F32_OE, 0, conv_interleave_32s_sse2, SPA_CPU_FLAG_SSE2), + MAKE(F32P, F32_OE, 0, conv_32sd_to_32s_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(F32P, F32_OE, 0, conv_interleave_32s_c), + MAKE(F32P, F32_OE, 0, conv_32sd_to_32s_c), MAKE(U32, F32, 0, conv_u32_to_f32_c), MAKE(U32, F32P, 0, conv_u32_to_f32d_c), @@ -287,14 +287,14 @@ /* u8 */ MAKE(U8, U8, 0, conv_copy8_c), MAKE(U8P, U8P, 0, conv_copy8d_c), - MAKE(U8, U8P, 0, conv_deinterleave_8_c), - MAKE(U8P, U8, 0, conv_interleave_8_c), + MAKE(U8, U8P, 0, conv_8_to_8d_c), + MAKE(U8P, U8, 0, conv_8d_to_8_c), /* s8 */ MAKE(S8, S8, 0, conv_copy8_c), MAKE(S8P, S8P, 0, conv_copy8d_c), - MAKE(S8, S8P, 0, conv_deinterleave_8_c), - MAKE(S8P, S8, 0, conv_interleave_8_c), + MAKE(S8, S8P, 0, conv_8_to_8d_c), + MAKE(S8P, S8, 0, conv_8d_to_8_c), /* alaw */ MAKE(ALAW, ALAW, 0, conv_copy8_c), @@ -304,44 +304,44 @@ /* s16 */ MAKE(S16, S16, 0, conv_copy16_c), MAKE(S16P, S16P, 0, conv_copy16d_c), - MAKE(S16, S16P, 0, conv_deinterleave_16_c), - MAKE(S16P, S16, 0, conv_interleave_16_c), + MAKE(S16, S16P, 0, conv_16_to_16d_c), + MAKE(S16P, S16, 0, conv_16d_to_16_c), /* s32 */ MAKE(S32, S32, 0, conv_copy32_c), MAKE(S32P, S32P, 0, conv_copy32d_c), #if defined (HAVE_SSE2) - MAKE(S32, S32P, 0, conv_deinterleave_32_sse2, SPA_CPU_FLAG_SSE2), + MAKE(S32, S32P, 0, conv_32_to_32d_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(S32, S32P, 0, conv_deinterleave_32_c), + MAKE(S32, S32P, 0, conv_32_to_32d_c), #if defined (HAVE_SSE2) - MAKE(S32P, S32, 0, conv_interleave_32_sse2, SPA_CPU_FLAG_SSE2), + MAKE(S32P, S32, 0, conv_32d_to_32_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(S32P, S32, 0, conv_interleave_32_c), + MAKE(S32P, S32, 0, conv_32d_to_32_c), /* s24 */ MAKE(S24, S24, 0, conv_copy24_c), MAKE(S24P, S24P, 0, conv_copy24d_c), - MAKE(S24, S24P, 0, conv_deinterleave_24_c), - MAKE(S24P, S24, 0, conv_interleave_24_c), + MAKE(S24, S24P, 0, conv_24_to_24d_c), + MAKE(S24P, S24, 0, conv_24d_to_24_c), /* s24_32 */ MAKE(S24_32, S24_32, 0, conv_copy32_c), MAKE(S24_32P, S24_32P, 0, conv_copy32d_c), #if defined (HAVE_SSE2) - MAKE(S24_32, S24_32P, 0, conv_deinterleave_32_sse2, SPA_CPU_FLAG_SSE2), + MAKE(S24_32, S24_32P, 0, conv_32_to_32d_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(S24_32, S24_32P, 0, conv_deinterleave_32_c), + MAKE(S24_32, S24_32P, 0, conv_32_to_32d_c), #if defined (HAVE_SSE2) - MAKE(S24_32P, S24_32, 0, conv_interleave_32_sse2, SPA_CPU_FLAG_SSE2), + MAKE(S24_32P, S24_32, 0, conv_32d_to_32_sse2, SPA_CPU_FLAG_SSE2), #endif - MAKE(S24_32P, S24_32, 0, conv_interleave_32_c), + MAKE(S24_32P, S24_32, 0, conv_32d_to_32_c), /* F64 */ MAKE(F64, F64, 0, conv_copy64_c), MAKE(F64P, F64P, 0, conv_copy64d_c), - MAKE(F64, F64P, 0, conv_deinterleave_64_c), - MAKE(F64P, F64, 0, conv_interleave_64_c), + MAKE(F64, F64P, 0, conv_64_to_64d_c), + MAKE(F64P, F64, 0, conv_64d_to_64_c), }; #undef MAKE
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/fmt-ops.h -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/fmt-ops.h
Changed
@@ -39,35 +39,33 @@ #define U8_MIN 0u #define U8_MAX 255u -#define U8_SCALE 127.5f +#define U8_SCALE 128.f #define U8_OFFS 128.f -#define U8_TO_F32(v) ((((uint8_t)(v)) * (1.0f / U8_OFFS)) - 1.0f) +#define U8_TO_F32(v) ((((uint8_t)(v)) * (1.0f / U8_SCALE)) - 1.0f) #define F32_TO_U8(v) (uint8_t)SPA_CLAMP((v) * U8_SCALE + U8_OFFS, U8_MIN, U8_MAX) #define F32_TO_U8_D(v,d) (uint8_t)SPA_CLAMP((v) * U8_SCALE + U8_OFFS + (d), U8_MIN, U8_MAX) -#define S8_MIN -127 +#define S8_MIN -128 #define S8_MAX 127 -#define S8_MAX_F 127.0f -#define S8_SCALE 127.0f +#define S8_SCALE 128.0f #define S8_TO_F32(v) (((int8_t)(v)) * (1.0f / S8_SCALE)) #define F32_TO_S8(v) (int8_t)SPA_CLAMP((v) * S8_SCALE, S8_MIN, S8_MAX) #define F32_TO_S8_D(v,d) (int8_t)SPA_CLAMP((v) * S8_SCALE + (d), S8_MIN, S8_MAX) #define U16_MIN 0u #define U16_MAX 65535u -#define U16_SCALE 32767.5f +#define U16_SCALE 32768.f #define U16_OFFS 32768.f -#define U16_TO_F32(v) ((((uint16_t)(v)) * (1.0f / U16_OFFS)) - 1.0) -#define U16S_TO_F32(v) (((uint16_t)bswap_16((uint16_t)(v)) * (1.0f / U16_OFFS)) - 1.0) +#define U16_TO_F32(v) ((((uint16_t)(v)) * (1.0f / U16_SCALE)) - 1.0f) +#define U16S_TO_F32(v) (((uint16_t)bswap_16((uint16_t)(v)) * (1.0f / U16_OFFS)) - 1.0f) #define F32_TO_U16(v) (uint16_t)SPA_CLAMP((v) * U16_SCALE + U16_OFFS, U16_MIN, U16_MAX) #define F32_TO_U16_D(v,d) (uint16_t)SPA_CLAMP((v) * U16_SCALE + U16_OFFS + (d), U16_MIN, U16_MAX) #define F32_TO_U16S(v) bswap_16(F32_TO_U16(v)) #define F32_TO_U16S_D(v,d) bswap_16(F32_TO_U16_D(v,d)) -#define S16_MIN -32767 +#define S16_MIN -32768 #define S16_MAX 32767 -#define S16_MAX_F 32767.0f -#define S16_SCALE 32767.0f +#define S16_SCALE 32768.0f #define S16_TO_F32(v) (((int16_t)(v)) * (1.0f / S16_SCALE)) #define S16S_TO_F32(v) (((int16_t)bswap_16(v)) * (1.0f / S16_SCALE)) #define F32_TO_S16(v) (int16_t)SPA_CLAMP((v) * S16_SCALE, S16_MIN, S16_MAX) @@ -77,31 +75,31 @@ #define U24_MIN 0u #define U24_MAX 16777215u -#define U24_SCALE 8388607.5f +#define U24_SCALE 8388608.f #define U24_OFFS 8388608.f -#define U24_TO_F32(v) ((((uint32_t)(v)) * (1.0f / U24_OFFS)) - 1.0) -#define F32_TO_U24(v) (uint32_t)SPA_CLAMP((v) * U24_SCALE + U24_OFFS, U24_MIN, U24_MAX) -#define F32_TO_U24_D(v,d) (uint32_t)SPA_CLAMP((v) * U24_SCALE + U24_OFFS + (d), U24_MIN, U24_MAX) +#define U24_TO_F32(v) ((u24_to_u32(v) * (1.0f / U24_SCALE)) - 1.0f) +#define F32_TO_U24(v) u32_to_u24(SPA_CLAMP((v) * U24_SCALE + U24_OFFS, U24_MIN, U24_MAX)) +#define F32_TO_U24_D(v,d) u32_to_u24(SPA_CLAMP((v) * U24_SCALE + U24_OFFS + (d), U24_MIN, U24_MAX)) -#define S24_MIN -8388607 +#define S24_MIN -8388608 #define S24_MAX 8388607 -#define S24_MAX_F 8388607.0f -#define S24_SCALE 8388607.0f -#define S24_TO_F32(v) (((int32_t)(v)) * (1.0f / S24_SCALE)) -#define F32_TO_S24(v) (int32_t)SPA_CLAMP((v) * S24_SCALE, S24_MIN, S24_MAX) -#define F32_TO_S24_D(v,d) (int32_t)SPA_CLAMP((v) * S24_SCALE + (d), S24_MIN, S24_MAX) +#define S24_SCALE 8388608.0f +#define S24_TO_F32(v) (s24_to_s32(v) * (1.0f / S24_SCALE)) +#define S24S_TO_F32(v) (s24_to_s32(bswap_s24(v)) * (1.0f / S24_SCALE)) +#define F32_TO_S24(v) s32_to_s24(SPA_CLAMP((v) * S24_SCALE, S24_MIN, S24_MAX)) +#define F32_TO_S24S(v) bswap_s24(F32_TO_S24(v)) +#define F32_TO_S24_D(v,d) s32_to_s24(SPA_CLAMP((v) * S24_SCALE + (d), S24_MIN, S24_MAX)) #define U32_MIN 0u -#define U32_MAX 4294967040u -#define U32_SCALE 2147483520.f -#define U32_OFFS 2147483520.f -#define U32_TO_F32(v) ((((uint32_t)(v)) * (1.0f / U32_OFFS)) - 1.0) +#define U32_MAX 4294967295 +#define U32_SCALE 2147483648.f +#define U32_OFFS 2147483648.f +#define U32_TO_F32(v) ((((uint32_t)(v)) * (1.0f / U32_SCALE)) - 1.0f) #define F32_TO_U32(v) (uint32_t)SPA_CLAMP((v) * U32_SCALE + U32_OFFS, U32_MIN, U32_MAX) #define F32_TO_U32_D(v,d) (uint32_t)SPA_CLAMP((v) * U32_SCALE + U32_OFFS + (d), U32_MIN, U32_MAX) -#define S32_MIN -2147483520 +#define S32_MIN -2147483648 #define S32_MAX 2147483520 -#define S32_MAX_F 2147483520.f #define S32_SCALE 2147483648.f #define S32_TO_F32(v) (((int32_t)(v)) * (1.0f / S32_SCALE)) #define S32S_TO_F32(v) (((int32_t)bswap_32(v)) * (1.0f / S32_SCALE)) @@ -112,88 +110,75 @@ #define U24_32_TO_F32(v) U32_TO_F32((v)<<8) #define U24_32S_TO_F32(v) U32_TO_F32(((int32_t)bswap_32(v))<<8) -#define F32_TO_U24_32(v) F32_TO_U24(v) -#define F32_TO_U24_32S(v) bswap_32(F32_TO_U24(v)) -#define F32_TO_U24_32_D(v,d) F32_TO_U24_D(v,d) -#define F32_TO_U24_32S_D(v,d) bswap_32(F32_TO_U24_D(v,d)) +#define F32_TO_U24_32(v) (uint32_t)SPA_CLAMP((v) * U24_SCALE + U24_OFFS, U24_MIN, U24_MAX) +#define F32_TO_U24_32S(v) bswap_32(F32_TO_U24_32(v)) +#define F32_TO_U24_32_D(v,d) (uint32_t)SPA_CLAMP((v) * U24_SCALE + U24_OFFS + (d), U24_MIN, U24_MAX) +#define F32_TO_U24_32S_D(v,d) bswap_32(F32_TO_U24_32_D(v,d)) #define S24_32_TO_F32(v) S32_TO_F32((v)<<8) #define S24_32S_TO_F32(v) S32_TO_F32(((int32_t)bswap_32(v))<<8) -#define F32_TO_S24_32(v) F32_TO_S24(v) -#define F32_TO_S24_32S(v) bswap_32(F32_TO_S24(v)) -#define F32_TO_S24_32_D(v,d) F32_TO_S24_D(v,d) -#define F32_TO_S24_32S_D(v,d) bswap_32(F32_TO_S24_D(v,d)) +#define F32_TO_S24_32(v) (int32_t)SPA_CLAMP((v) * S24_SCALE, S24_MIN, S24_MAX) +#define F32_TO_S24_32S(v) bswap_32(F32_TO_S24_32(v)) +#define F32_TO_S24_32_D(v,d) (int32_t)SPA_CLAMP((v) * S24_SCALE + (d), S24_MIN, S24_MAX) +#define F32_TO_S24_32S_D(v,d) bswap_32(F32_TO_S24_32_D(v,d)) -static inline uint32_t read_u24(const void *src) -{ - const uint8_t *s = src; +typedef struct { #if __BYTE_ORDER == __LITTLE_ENDIAN - return (((uint32_t)s2 << 16) | ((uint32_t)(uint8_t)s1 << 8) | (uint32_t)(uint8_t)s0); + uint8_t v3; + uint8_t v2; + uint8_t v1; #else - return (((uint32_t)s0 << 16) | ((uint32_t)(uint8_t)s1 << 8) | (uint32_t)(uint8_t)s2); + uint8_t v1; + uint8_t v2; + uint8_t v3; #endif -} +} __attribute__ ((packed)) uint24_t; -static inline int32_t read_s24(const void *src) -{ - const int8_t *s = src; +typedef struct { #if __BYTE_ORDER == __LITTLE_ENDIAN - return (((int32_t)s2 << 16) | ((uint32_t)(uint8_t)s1 << 8) | (uint32_t)(uint8_t)s0); + uint8_t v3; + uint8_t v2; + int8_t v1; #else - return (((int32_t)s0 << 16) | ((uint32_t)(uint8_t)s1 << 8) | (uint32_t)(uint8_t)s2); + int8_t v1; + uint8_t v2; + uint8_t v3; #endif +} __attribute__ ((packed)) int24_t; + +static inline uint32_t u24_to_u32(uint24_t src) +{ + return ((uint32_t)src.v1 << 16) | ((uint32_t)src.v2 << 8) | (uint32_t)src.v3; } -static inline int32_t read_s24s(const void *src) +#define U32_TO_U24(s) (uint24_t) { .v1 = (uint8_t)(((uint32_t)s) >> 16), \ + .v2 = (uint8_t)(((uint32_t)s) >> 8), .v3 = (uint8_t)((uint32_t)s) } + +static inline uint24_t u32_to_u24(uint32_t src) { - const int8_t *s = src; -#if __BYTE_ORDER == __LITTLE_ENDIAN - return (((int32_t)s0 << 16) | ((uint32_t)(uint8_t)s1 << 8) | (uint32_t)(uint8_t)s2); -#else - return (((int32_t)s2 << 16) | ((uint32_t)(uint8_t)s1 << 8) | (uint32_t)(uint8_t)s0); -#endif + return U32_TO_U24(src); } -static inline void write_u24(void *dst, uint32_t val) +static inline int32_t s24_to_s32(int24_t src) { - uint8_t *d = dst; -#if __BYTE_ORDER == __LITTLE_ENDIAN - d0 = (uint8_t) (val); - d1 = (uint8_t) (val >> 8); - d2 = (uint8_t) (val >> 16); -#else - d0 = (uint8_t) (val >> 16); - d1 = (uint8_t) (val >> 8); - d2 = (uint8_t) (val); -#endif + return ((int32_t)src.v1 << 16) | ((uint32_t)src.v2 << 8) | (uint32_t)src.v3; } -static inline void write_s24(void *dst, int32_t val) +#define S32_TO_S24(s) (int24_t) { .v1 = (int8_t)(((int32_t)s) >> 16), \ + .v2 = (uint8_t)(((uint32_t)s) >> 8), .v3 = (uint8_t)((uint32_t)s) } + +static inline int24_t s32_to_s24(int32_t src) { - uint8_t *d = dst; -#if __BYTE_ORDER == __LITTLE_ENDIAN - d0 = (uint8_t) (val); - d1 = (uint8_t) (val >> 8); - d2 = (uint8_t) (val >> 16); -#else - d0 = (uint8_t) (val >> 16); - d1 = (uint8_t) (val >> 8); - d2 = (uint8_t) (val); -#endif + return S32_TO_S24(src); } -static inline void write_s24s(void *dst, int32_t val) +static inline uint24_t bswap_u24(uint24_t src) { - uint8_t *d = dst; -#if __BYTE_ORDER == __LITTLE_ENDIAN - d0 = (uint8_t) (val >> 16); - d1 = (uint8_t) (val >> 8); - d2 = (uint8_t) (val); -#else - d0 = (uint8_t) (val); - d1 = (uint8_t) (val >> 8); - d2 = (uint8_t) (val >> 16); -#endif + return (uint24_t) { .v1 = src.v3, .v2 = src.v2, .v3 = src.v1 }; +} +static inline int24_t bswap_s24(int24_t src) +{ + return (int24_t) { .v1 = src.v3, .v2 = src.v2, .v3 = src.v1 }; } #define NS_MAX 8 @@ -206,7 +191,6 @@ }; struct convert { - uint32_t quantize; uint32_t noise; #define DITHER_METHOD_NONE 0 #define DITHER_METHOD_RECTANGULAR 1 @@ -383,20 +367,20 @@ DEFINE_FUNCTION(f32_to_f64d, c); DEFINE_FUNCTION(f32d_to_f64, c); DEFINE_FUNCTION(f32d_to_f64s, c); -DEFINE_FUNCTION(deinterleave_8, c); -DEFINE_FUNCTION(deinterleave_16, c); -DEFINE_FUNCTION(deinterleave_24, c); -DEFINE_FUNCTION(deinterleave_32, c); -DEFINE_FUNCTION(deinterleave_32s, c); -DEFINE_FUNCTION(deinterleave_64, c); -DEFINE_FUNCTION(deinterleave_64s, c); -DEFINE_FUNCTION(interleave_8, c); -DEFINE_FUNCTION(interleave_16, c); -DEFINE_FUNCTION(interleave_24, c); -DEFINE_FUNCTION(interleave_32, c); -DEFINE_FUNCTION(interleave_32s, c); -DEFINE_FUNCTION(interleave_64, c); -DEFINE_FUNCTION(interleave_64s, c); +DEFINE_FUNCTION(8_to_8d, c); +DEFINE_FUNCTION(16_to_16d, c); +DEFINE_FUNCTION(24_to_24d, c); +DEFINE_FUNCTION(32_to_32d, c); +DEFINE_FUNCTION(32s_to_32sd, c); +DEFINE_FUNCTION(64_to_64d, c); +DEFINE_FUNCTION(64s_to_64sd, c); +DEFINE_FUNCTION(8d_to_8, c); +DEFINE_FUNCTION(16d_to_16, c); +DEFINE_FUNCTION(24d_to_24, c); +DEFINE_FUNCTION(32d_to_32, c); +DEFINE_FUNCTION(32sd_to_32s, c); +DEFINE_FUNCTION(64d_to_64, c); +DEFINE_FUNCTION(64sd_to_64s, c); #if defined(HAVE_NEON) DEFINE_FUNCTION(s16_to_f32d_2, neon); @@ -414,10 +398,10 @@ DEFINE_FUNCTION(f32d_to_s16_2, sse2); DEFINE_FUNCTION(f32d_to_s16, sse2); DEFINE_FUNCTION(f32d_to_s16d, sse2); -DEFINE_FUNCTION(deinterleave_32, sse2); -DEFINE_FUNCTION(deinterleave_32s, sse2); -DEFINE_FUNCTION(interleave_32, sse2); -DEFINE_FUNCTION(interleave_32s, sse2); +DEFINE_FUNCTION(32_to_32d, sse2); +DEFINE_FUNCTION(32s_to_32sd, sse2); +DEFINE_FUNCTION(32d_to_32, sse2); +DEFINE_FUNCTION(32sd_to_32s, sse2); #endif #if defined(HAVE_SSSE3) DEFINE_FUNCTION(s24_to_f32d, ssse3);
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/resample-native.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/resample-native.c
Changed
@@ -58,23 +58,24 @@ return sin(x) / x; } -#if 0 static inline double window_blackman(double x, double n_taps) { - double alpha = 0.232; + double alpha = 0.232, r; x = 2.0 * M_PI * x / n_taps; - return (1.0 - alpha) / 2.0 + (1.0 / 2.0) * cos(x) + - (alpha / 2.0) * cos(2 * x); + r = (1.0 - alpha) / 2.0 + (1.0 / 2.0) * cos(x) + + (alpha / 2.0) * cos(2.0 * x); + return r; } -#else static inline double window_cosh(double x, double n_taps) { - double R = 95.0; + double R = 190.0, r; double A = -325.1E-6 * (R * R) + 0.1677 * R - 3.149; - x = 2.0 * M_PI * x / n_taps; - return cosh(A * sqrt(1 - pow(x / M_PI, 2))) / cosh(A); + x = 2.0 * x / n_taps; + r = cosh(A * sqrt(1 - pow(x, 2))) / cosh(A); + return r; } -#endif + +#define window window_blackman static int build_filter(float *taps, uint32_t stride, uint32_t n_taps, uint32_t n_phases, double cutoff) { @@ -86,7 +87,7 @@ /* exploit symmetry in filter taps */ taps(n_phases - i) * stride + n_taps12 + j = tapsi * stride + (n_taps12 - j - 1) = - cutoff * sinc(t * cutoff) * window_cosh(t, n_taps); + cutoff * sinc(t * cutoff) * window(t, n_taps); } } return 0;
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/test-audioconvert.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/test-audioconvert.c
Changed
@@ -36,6 +36,7 @@ #include <spa/param/audio/format.h> #include <spa/param/audio/format-utils.h> #include <spa/node/node.h> +#include <spa/node/io.h> #include <spa/debug/mem.h> #include <spa/support/log-impl.h> @@ -71,6 +72,7 @@ size_t size; int res; struct spa_support support1; + struct spa_dict_item items2; const struct spa_handle_factory *factory; void *iface; @@ -86,9 +88,11 @@ ctx->convert_handle = calloc(1, size); spa_assert_se(ctx->convert_handle != NULL); + items0 = SPA_DICT_ITEM_INIT("clock.quantum-limit", "8192"); + res = spa_handle_factory_init(factory, ctx->convert_handle, - NULL, + &SPA_DICT_INIT(items, 1), support, 1); spa_assert_se(res >= 0); @@ -510,6 +514,351 @@ return 0; } +static int setup_direction(struct context *ctx, enum spa_direction direction, uint32_t mode, + struct spa_audio_info_raw *info) +{ + struct spa_pod_builder b = { 0 }; + uint8_t buffer1024; + struct spa_pod *param, *format; + int res; + uint32_t i; + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + format = spa_format_audio_raw_build(&b, SPA_PARAM_Format, info); + + switch (mode) { + case SPA_PARAM_PORT_CONFIG_MODE_dsp: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, + SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction), + SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(mode), + SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(format)); + break; + + case SPA_PARAM_PORT_CONFIG_MODE_convert: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, + SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction), + SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(mode)); + break; + default: + return -EINVAL; + } + res = spa_node_set_param(ctx->convert_node, SPA_PARAM_PortConfig, 0, param); + spa_assert_se(res == 0); + + switch (mode) { + case SPA_PARAM_PORT_CONFIG_MODE_convert: + res = spa_node_port_set_param(ctx->convert_node, direction, 0, + SPA_PARAM_Format, 0, format); + spa_assert_se(res == 0); + break; + case SPA_PARAM_PORT_CONFIG_MODE_dsp: + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + format = spa_format_audio_dsp_build(&b, SPA_PARAM_Format, + &SPA_AUDIO_INFO_DSP_INIT( + .format = SPA_AUDIO_FORMAT_F32P)); + for (i = 0; i < info->channels; i++) { + res = spa_node_port_set_param(ctx->convert_node, direction, i, + SPA_PARAM_Format, 0, format); + spa_assert_se(res == 0); + } + break; + default: + return -EINVAL; + } + return 0; +} + +struct buffer { + struct spa_buffer buffer; + struct spa_data datasMAX_PORTS; + struct spa_chunk chunksMAX_PORTS; +}; + +struct data { + uint32_t mode; + struct spa_audio_info_raw info; + uint32_t ports; + uint32_t planes; + const void *dataMAX_PORTS; + uint32_t size; +}; + +static int run_convert(struct context *ctx, struct data *in_data, + struct data *out_data) +{ + struct spa_command cmd; + int res; + uint32_t i, j, k; + struct buffer in_buffersin_data->ports; + struct buffer out_buffersout_data->ports; + struct spa_io_buffers in_ioin_data->ports; + struct spa_io_buffers out_ioout_data->ports; + + setup_direction(ctx, SPA_DIRECTION_INPUT, in_data->mode, &in_data->info); + setup_direction(ctx, SPA_DIRECTION_OUTPUT, out_data->mode, &out_data->info); + + cmd = SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Start); + res = spa_node_send_command(ctx->convert_node, &cmd); + spa_assert_se(res == 0); + + for (i = 0, k = 0; i < in_data->ports; i++) { + struct buffer *b = &in_buffersi; + struct spa_buffer *buffers1; + spa_zero(*b); + b->buffer.datas = b->datas; + b->buffer.n_datas = in_data->planes; + + for (j = 0; j < in_data->planes; j++, k++) { + b->datasj.type = SPA_DATA_MemPtr; + b->datasj.flags = 0; + b->datasj.fd = -1; + b->datasj.mapoffset = 0; + b->datasj.maxsize = in_data->size; + b->datasj.data = (void *)in_data->datak; + b->datasj.chunk = &b->chunksj; + b->datasj.chunk->offset = 0; + b->datasj.chunk->size = in_data->size; + b->datasj.chunk->stride = 0; + } + buffers0 = &b->buffer; + res = spa_node_port_use_buffers(ctx->convert_node, SPA_DIRECTION_INPUT, i, + 0, buffers, 1); + spa_assert_se(res == 0); + + in_ioi.status = SPA_STATUS_HAVE_DATA; + in_ioi.buffer_id = 0; + + res = spa_node_port_set_io(ctx->convert_node, SPA_DIRECTION_INPUT, i, + SPA_IO_Buffers, &in_ioi, sizeof(in_ioi)); + spa_assert_se(res == 0); + } + for (i = 0; i < out_data->ports; i++) { + struct buffer *b = &out_buffersi; + struct spa_buffer *buffers1; + spa_zero(*b); + b->buffer.datas = b->datas; + b->buffer.n_datas = out_data->planes; + + for (j = 0; j < out_data->planes; j++) { + b->datasj.type = SPA_DATA_MemPtr; + b->datasj.flags = 0; + b->datasj.fd = -1; + b->datasj.mapoffset = 0; + b->datasj.maxsize = out_data->size; + b->datasj.data = calloc(1, out_data->size); + b->datasj.chunk = &b->chunksj; + b->datasj.chunk->offset = 0; + b->datasj.chunk->size = 0; + b->datasj.chunk->stride = 0; + } + buffers0 = &b->buffer; + res = spa_node_port_use_buffers(ctx->convert_node, + SPA_DIRECTION_OUTPUT, i, 0, buffers, 1); + spa_assert_se(res == 0); + + out_ioi.status = SPA_STATUS_NEED_DATA; + out_ioi.buffer_id = -1; + + res = spa_node_port_set_io(ctx->convert_node, SPA_DIRECTION_OUTPUT, i, + SPA_IO_Buffers, &out_ioi, sizeof(out_ioi)); + spa_assert_se(res == 0); + } + + res = spa_node_process(ctx->convert_node); + spa_assert_se(res == (SPA_STATUS_NEED_DATA | SPA_STATUS_HAVE_DATA)); + + for (i = 0, k = 0; i < out_data->ports; i++) { + struct buffer *b = &out_buffersi; + + spa_assert_se(out_ioi.status == SPA_STATUS_HAVE_DATA); + spa_assert_se(out_ioi.buffer_id == 0); + + for (j = 0; j < out_data->planes; j++, k++) { + spa_assert_se(b->datasj.chunk->offset == 0); + spa_assert_se(b->datasj.chunk->size == out_data->size); + + res = memcmp(b->datasj.data, out_data->datak, out_data->size); + if (res != 0) { + fprintf(stderr, "error plane %d\n", j); + spa_debug_mem(0, b->datasj.data, out_data->size); + spa_debug_mem(0, out_data->dataj, out_data->size); + } + spa_assert_se(res == 0); + + free(b->datasj.data); + } + } + cmd = SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend); + res = spa_node_send_command(ctx->convert_node, &cmd); + spa_assert_se(res == 0); + + return 0; +} + +static const float data_f32p_1 = { 0.1f, 0.1f, 0.1f, 0.1f }; +static const float data_f32p_2 = { 0.2f, 0.2f, 0.2f, 0.2f }; +static const float data_f32p_3 = { 0.3f, 0.3f, 0.3f, 0.3f }; +static const float data_f32p_4 = { 0.4f, 0.4f, 0.4f, 0.4f }; +static const float data_f32p_5 = { 0.5f, 0.5f, 0.5f, 0.5f }; +static const float data_f32p_6 = { 0.6f, 0.6f, 0.6f, 0.6f }; + +static const float data_f32_5p1 = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, + 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, + 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, + 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f }; +static const float data_f32_5p1_remapped = { 0.1f, 0.2f, 0.5f, 0.6f, 0.3f, 0.4f, + 0.1f, 0.2f, 0.5f, 0.6f, 0.3f, 0.4f, + 0.1f, 0.2f, 0.5f, 0.6f, 0.3f, 0.4f, + 0.1f, 0.2f, 0.5f, 0.6f, 0.3f, 0.4f }; + +struct data dsp_5p1 = { + .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp, + .info = SPA_AUDIO_INFO_RAW_INIT( + .format = SPA_AUDIO_FORMAT_F32, + .rate = 48000, + .channels = 6, + .position = { + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_LFE, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR, + }), + .ports = 6, + .planes = 1, + .data = { data_f32p_1, data_f32p_2, data_f32p_3, data_f32p_4, data_f32p_5, data_f32p_6, }, + .size = sizeof(float) * 4 +}; + +struct data dsp_5p1_remapped = { + .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp, + .info = SPA_AUDIO_INFO_RAW_INIT( + .format = SPA_AUDIO_FORMAT_F32, + .rate = 48000, + .channels = 6, + .position = { + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR, + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_LFE, + }), + .ports = 6, + .planes = 1, + .data = { data_f32p_1, data_f32p_2, data_f32p_5, data_f32p_6, data_f32p_3, data_f32p_4, }, + .size = sizeof(float) * 4 +}; + +struct data conv_f32_48000_5p1 = { + .mode = SPA_PARAM_PORT_CONFIG_MODE_convert, + .info = SPA_AUDIO_INFO_RAW_INIT( + .format = SPA_AUDIO_FORMAT_F32, + .rate = 48000, + .channels = 6, + .position = { + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_LFE, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR, + }), + .ports = 1, + .planes = 1, + .data = { data_f32_5p1 }, + .size = sizeof(data_f32_5p1) +}; + +struct data conv_f32_48000_5p1_remapped = { + .mode = SPA_PARAM_PORT_CONFIG_MODE_convert, + .info = SPA_AUDIO_INFO_RAW_INIT( + .format = SPA_AUDIO_FORMAT_F32, + .rate = 48000, + .channels = 6, + .position = { + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR, + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_LFE, + }), + .ports = 1, + .planes = 1, + .data = { data_f32_5p1_remapped }, + .size = sizeof(data_f32_5p1_remapped) +}; + +struct data conv_f32p_48000_5p1 = { + .mode = SPA_PARAM_PORT_CONFIG_MODE_convert, + .info = SPA_AUDIO_INFO_RAW_INIT( + .format = SPA_AUDIO_FORMAT_F32P, + .rate = 48000, + .channels = 6, + .position = { + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_LFE, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR, + }), + .ports = 1, + .planes = 6, + .data = { data_f32p_1, data_f32p_2, data_f32p_3, data_f32p_4, data_f32p_5, data_f32p_6, }, + .size = sizeof(float) * 4 +}; + +struct data conv_f32p_48000_5p1_remapped = { + .mode = SPA_PARAM_PORT_CONFIG_MODE_convert, + .info = SPA_AUDIO_INFO_RAW_INIT( + .format = SPA_AUDIO_FORMAT_F32P, + .rate = 48000, + .channels = 6, + .position = { + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR, + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_LFE, + }), + .ports = 1, + .planes = 6, + .data = { data_f32p_1, data_f32p_2, data_f32p_5, data_f32p_6, data_f32p_3, data_f32p_4, }, + .size = sizeof(float) * 4 +}; + +static int test_convert_remap_dsp(struct context *ctx) +{ + run_convert(ctx, &dsp_5p1, &conv_f32_48000_5p1); + run_convert(ctx, &dsp_5p1, &conv_f32p_48000_5p1); + run_convert(ctx, &dsp_5p1, &conv_f32_48000_5p1_remapped); + run_convert(ctx, &dsp_5p1, &conv_f32p_48000_5p1_remapped); + run_convert(ctx, &dsp_5p1_remapped, &conv_f32_48000_5p1); + run_convert(ctx, &dsp_5p1_remapped, &conv_f32p_48000_5p1); + run_convert(ctx, &dsp_5p1_remapped, &conv_f32_48000_5p1_remapped); + run_convert(ctx, &dsp_5p1_remapped, &conv_f32p_48000_5p1_remapped); + return 0; +} + +static int test_convert_remap_conv(struct context *ctx) +{ + run_convert(ctx, &conv_f32_48000_5p1, &dsp_5p1); + run_convert(ctx, &conv_f32_48000_5p1, &dsp_5p1_remapped); + run_convert(ctx, &conv_f32p_48000_5p1, &dsp_5p1); + run_convert(ctx, &conv_f32p_48000_5p1, &dsp_5p1_remapped); + run_convert(ctx, &conv_f32_48000_5p1_remapped, &dsp_5p1); + run_convert(ctx, &conv_f32_48000_5p1_remapped, &dsp_5p1_remapped); + run_convert(ctx, &conv_f32p_48000_5p1_remapped, &dsp_5p1); + run_convert(ctx, &conv_f32p_48000_5p1_remapped, &dsp_5p1_remapped); + return 0; +} + int main(int argc, char *argv) { struct context ctx; @@ -531,6 +880,9 @@ test_set_in_format2(&ctx); test_set_out_format(&ctx); + test_convert_remap_dsp(&ctx); + test_convert_remap_conv(&ctx); + clean_context(&ctx); return 0;
View file
pipewire-0.3.53.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c -> pipewire-0.3.54.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c
Changed
@@ -50,7 +50,7 @@ { int res = memcmp(m1, m2, size); if (res != 0) { - fprintf(stderr, "%d %d:\n", i, j); + fprintf(stderr, "%d %d %zd:\n", i, j, size); spa_debug_mem(0, m1, size); spa_debug_mem(0, m2, size); } @@ -81,19 +81,19 @@ tp0 = temp_in; switch(in_size) { case 1: - conv_interleave_8_c(&conv, tp, ip, N_SAMPLES); + conv_8d_to_8_c(&conv, tp, ip, N_SAMPLES); break; case 2: - conv_interleave_16_c(&conv, tp, ip, N_SAMPLES); + conv_16d_to_16_c(&conv, tp, ip, N_SAMPLES); break; case 3: - conv_interleave_24_c(&conv, tp, ip, N_SAMPLES); + conv_24d_to_24_c(&conv, tp, ip, N_SAMPLES); break; case 4: - conv_interleave_32_c(&conv, tp, ip, N_SAMPLES); + conv_32d_to_32_c(&conv, tp, ip, N_SAMPLES); break; case 8: - conv_interleave_64_c(&conv, tp, ip, N_SAMPLES); + conv_64d_to_64_c(&conv, tp, ip, N_SAMPLES); break; default: fprintf(stderr, "unknown size %zd\n", in_size); @@ -125,10 +125,40 @@ } } +static void test_f32_s8(void) +{ + static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; + static const int8_t out = { 0, 127, -128, 64, 192, 127, -128 }; + + run_test("test_f32_s8", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + true, true, conv_f32_to_s8_c); + run_test("test_f32d_s8", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + false, true, conv_f32d_to_s8_c); + run_test("test_f32_s8d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + true, false, conv_f32_to_s8d_c); + run_test("test_f32d_s8d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + false, false, conv_f32d_to_s8d_c); +} + +static void test_s8_f32(void) +{ + static const int8_t in = { 0, 127, -128, 64, 192, }; + static const float out = { 0.0f, 0.9921875f, -1.0f, 0.5f, -0.5f, }; + + run_test("test_s8_f32", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + true, true, conv_s8_to_f32_c); + run_test("test_s8d_f32", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + false, true, conv_s8d_to_f32_c); + run_test("test_s8_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + true, false, conv_s8_to_f32d_c); + run_test("test_s8d_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + false, false, conv_s8d_to_f32d_c); +} + static void test_f32_u8(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const uint8_t out = { 128, 255, 0, 191, 64, 255, 0, }; + static const uint8_t out = { 128, 255, 0, 192, 64, 255, 0, }; run_test("test_f32_u8", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_u8_c); @@ -158,7 +188,7 @@ static void test_f32_u16(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const uint16_t out = { 32767, 65535, 0, 49150, 16383, 65535, 0 }; + static const uint16_t out = { 32768, 65535, 0, 49152, 16384, 65535, 0 }; run_test("test_f32_u16", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_u16_c); @@ -168,8 +198,8 @@ static void test_u16_f32(void) { - static const uint16_t in = { 32767, 65535, 0, 49150, 16383, }; - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999847412f, -0.4999847412f }; + static const uint16_t in = { 32768, 65535, 0, 49152, 16384, }; + static const float out = { 0.0f, 0.999969482422f, -1.0f, 0.5f, -0.5f }; run_test("test_u16_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_u16_to_f32d_c); @@ -180,7 +210,7 @@ static void test_f32_s16(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const int16_t out = { 0, 32767, -32767, 16383, -16383, 32767, -32767 }; + static const int16_t out = { 0, 32767, -32768, 16384, -16384, 32767, -32768 }; run_test("test_f32_s16", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_s16_c); @@ -192,16 +222,26 @@ false, false, conv_f32d_to_s16d_c); #if defined(HAVE_SSE2) if (cpu_flags & SPA_CPU_FLAG_SSE2) { + run_test("test_f32_s16_sse2", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + true, true, conv_f32_to_s16_sse2); run_test("test_f32d_s16_sse2", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), false, true, conv_f32d_to_s16_sse2); + run_test("test_f32d_s16d_sse2", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + false, false, conv_f32d_to_s16d_sse2); + } +#endif +#if defined(HAVE_AVX2) + if (cpu_flags & SPA_CPU_FLAG_AVX2) { + run_test("test_f32d_s16_avx2", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + false, true, conv_f32d_to_s16_avx2); } #endif } static void test_s16_f32(void) { - static const int16_t in = { 0, 32767, -32767, 16383, -16383, }; - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999847412f, -0.4999847412f }; + static const int16_t in = { 0, 32767, -32768, 16384, -16384, }; + static const float out = { 0.0f, 0.999969482422f, -1.0f, 0.5f, -0.5f }; run_test("test_s16_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_s16_to_f32d_c); @@ -217,13 +257,19 @@ true, false, conv_s16_to_f32d_sse2); } #endif +#if defined(HAVE_AVX2) + if (cpu_flags & SPA_CPU_FLAG_AVX2) { + run_test("test_s16_f32d_avx2", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + true, false, conv_s16_to_f32d_avx2); + } +#endif } static void test_f32_u32(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const uint32_t out = { 0, 0x7fffff00, 0x80000100, 0x3fffff00, 0xc0000100, - 0x7fffff00, 0x80000100 }; + static const uint32_t out = { 0x80000000, 0xffffffff, 0x0, 0xc0000000, 0x40000000, + 0xffffffff, 0x0 }; run_test("test_f32_u32", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_u32_c); @@ -233,8 +279,8 @@ static void test_u32_f32(void) { - static const uint32_t in = { 0, 0x7fffff00, 0x80000100, 0x3fffff00, 0xc0000100 }; - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + static const uint32_t in = { 0x80000000, 0xffffffff, 0x0, 0xc0000000, 0x40000000 }; + static const float out = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, }; run_test("test_u32_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_u32_to_f32d_c); @@ -245,8 +291,8 @@ static void test_f32_s32(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const int32_t out = { 0, 0x7fffff00, 0x80000100, 0x3fffff00, 0xc0000100, - 0x7fffff00, 0x80000100 }; + static const int32_t out = { 0, 0x7fffff80, 0x80000000, 0x40000000, 0xc0000000, + 0x7fffff80, 0x80000000 }; run_test("test_f32_s32", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_s32_c); @@ -262,12 +308,18 @@ false, true, conv_f32d_to_s32_sse2); } #endif +#if defined(HAVE_AVX2) + if (cpu_flags & SPA_CPU_FLAG_AVX2) { + run_test("test_f32d_s32_avx2", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + false, true, conv_f32d_to_s32_avx2); + } +#endif } static void test_s32_f32(void) { - static const int32_t in = { 0, 0x7fffff00, 0x80000100, 0x3fffff00, 0xc0000100 }; - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + static const int32_t in = { 0, 0x7fffff80, 0x80000000, 0x40000000, 0xc0000000 }; + static const float out = { 0.0f, 0.999999940395f, -1.0f, 0.5, -0.5, }; run_test("test_s32_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_s32_to_f32d_c); @@ -283,18 +335,20 @@ true, false, conv_s32_to_f32d_sse2); } #endif +#if defined(HAVE_AVX2) + if (cpu_flags & SPA_CPU_FLAG_AVX2) { + run_test("test_s32_f32d_avx2", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), + true, false, conv_s32_to_f32d_avx2); + } +#endif } static void test_f32_u24(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; -#if __BYTE_ORDER == __LITTLE_ENDIAN - static const uint8_t out = { 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80, - 0xff, 0xff, 0x3f, 0x01, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80 }; -#else - static const uint8_t out = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01, - 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01 }; -#endif + static const uint24_t out = { U32_TO_U24(0x00800000), U32_TO_U24(0xffffff), + U32_TO_U24(0x000000), U32_TO_U24(0xc00000), U32_TO_U24(0x400000), + U32_TO_U24(0xffffff), U32_TO_U24(0x000000) }; run_test("test_f32_u24", in, sizeof(in0), out, 3, SPA_N_ELEMENTS(in), true, true, conv_f32_to_u24_c); @@ -304,14 +358,9 @@ static void test_u24_f32(void) { -#if __BYTE_ORDER == __LITTLE_ENDIAN - static const uint8_t in = { 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80, - 0xff, 0xff, 0x3f, 0x01, 0x00, 0xc0, }; -#else - static const uint8_t in = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01, - 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x01, }; -#endif - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + static const uint24_t in = { U32_TO_U24(0x00800000), U32_TO_U24(0xffffff), + U32_TO_U24(0x000000), U32_TO_U24(0xc00000), U32_TO_U24(0x400000) }; + static const float out = { 0.0f, 0.999999880791f, -1.0f, 0.5, -0.5, }; run_test("test_u24_f32d", in, 3, out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_u24_to_f32d_c); @@ -322,13 +371,9 @@ static void test_f32_s24(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; -#if __BYTE_ORDER == __LITTLE_ENDIAN - static const uint8_t out = { 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80, - 0xff, 0xff, 0x3f, 0x01, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80 }; -#else - static const uint8_t out = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01, - 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01 }; -#endif + static const int24_t out = { S32_TO_S24(0), S32_TO_S24(0x7fffff), + S32_TO_S24(0xff800000), S32_TO_S24(0x400000), S32_TO_S24(0xc00000), + S32_TO_S24(0x7fffff), S32_TO_S24(0xff800000) }; run_test("test_f32_s24", in, sizeof(in0), out, 3, SPA_N_ELEMENTS(in), true, true, conv_f32_to_s24_c); @@ -342,14 +387,9 @@ static void test_s24_f32(void) { -#if __BYTE_ORDER == __LITTLE_ENDIAN - static const uint8_t in = { 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80, - 0xff, 0xff, 0x3f, 0x01, 0x00, 0xc0, }; -#else - static const uint8_t in = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01, - 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x01, }; -#endif - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + static const int24_t in = { S32_TO_S24(0), S32_TO_S24(0x7fffff), + S32_TO_S24(0xff800000), S32_TO_S24(0x400000), S32_TO_S24(0xc00000) }; + static const float out = { 0.0f, 0.999999880791f, -1.0f, 0.5f, -0.5f, }; run_test("test_s24_f32d", in, 3, out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_s24_to_f32d_c); @@ -377,13 +417,19 @@ true, false, conv_s24_to_f32d_sse41); } #endif +#if defined(HAVE_AVX2) + if (cpu_flags & SPA_CPU_FLAG_AVX2) { + run_test("test_s24_f32d_avx2", in, 3, out, sizeof(out0), SPA_N_ELEMENTS(out), + true, false, conv_s24_to_f32d_avx2); + } +#endif } static void test_f32_u24_32(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const uint32_t out = { 0, 0x7fffff, 0xff800001, 0x3fffff, 0xffc00001, - 0x7fffff, 0xff800001 }; + static const uint32_t out = { 0x800000, 0xffffff, 0x0, 0xc00000, 0x400000, + 0xffffff, 0x000000 }; run_test("test_f32_u24_32", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_u24_32_c); @@ -393,8 +439,8 @@ static void test_u24_32_f32(void) { - static const uint32_t in = { 0, 0x7fffff, 0xff800001, 0x3fffff, 0xffc00001 }; - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + static const uint32_t in = { 0x800000, 0xffffff, 0x0, 0xc00000, 0x400000 }; + static const float out = { 0.0f, 0.999999880791f, -1.0f, 0.5f, -0.5f, }; run_test("test_u24_32_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_u24_32_to_f32d_c); @@ -405,8 +451,8 @@ static void test_f32_s24_32(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const int32_t out = { 0, 0x7fffff, 0xff800001, 0x3fffff, 0xffc00001, - 0x7fffff, 0xff800001 }; + static const int32_t out = { 0, 0x7fffff, 0xff800000, 0x400000, 0xffc00000, + 0x7fffff, 0xff800000 }; run_test("test_f32_s24_32", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_s24_32_c); @@ -420,8 +466,8 @@ static void test_s24_32_f32(void) { - static const int32_t in = { 0, 0x7fffff, 0xff800001, 0x3fffff, 0xffc00001 }; - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + static const int32_t in = { 0, 0x7fffff, 0xff800000, 0x400000, 0xffc00000 }; + static const float out = { 0.0f, 0.999999880791f, -1.0f, 0.5f, -0.5f, }; run_test("test_s24_32_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_s24_32_to_f32d_c); @@ -435,8 +481,8 @@ static void test_f64_f32(void) { - static const double in = { 0.0, 1.0, -1.0, 0.4999999404, -0.4999999404, }; - static const float out = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + static const double in = { 0.0, 1.0, -1.0, 0.5, -0.5, }; + static const float out = { 0.0, 1.0, -1.0, 0.5, -0.5, }; run_test("test_f64_f32d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, false, conv_f64_to_f32d_c); @@ -451,7 +497,7 @@ static void test_f32_f64(void) { static const float in = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; - static const double out = { 0.0, 1.0, -1.0, 0.5, -0.5, 1.1, -1.1 }; + static const double out = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; run_test("test_f32_f64", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), true, true, conv_f32_to_f64_c); @@ -462,11 +508,131 @@ run_test("test_f32d_f64d", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out), false, false, conv_f32d_to_f64d_c); } + +static void test_lossless_s8(void) +{ + int8_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = S8_MIN; i < S8_MAX; i+=1) { + float v = S8_TO_F32(i); + int8_t t = F32_TO_S8(v); + spa_assert_se(i == t); + } +} + +static void test_lossless_u8(void) +{ + uint8_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = U8_MIN; i < U8_MAX; i+=1) { + float v = U8_TO_F32(i); + uint8_t t = F32_TO_U8(v); + spa_assert_se(i == t); + } +} +static void test_lossless_s16(void) +{ + int16_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = S16_MIN; i < S16_MAX; i+=3) { + float v = S16_TO_F32(i); + int16_t t = F32_TO_S16(v); + spa_assert_se(i == t); + } +} + +static void test_lossless_u16(void) +{ + uint32_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = U16_MIN; i < U16_MAX; i+=3) { + float v = U16_TO_F32(i); + uint16_t t = F32_TO_U16(v); + spa_assert_se(i == t); + } +} + +static void test_lossless_s24(void) +{ + int32_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = S24_MIN; i < S24_MAX; i+=13) { + float v = S24_TO_F32(s32_to_s24(i)); + int32_t t = s24_to_s32(F32_TO_S24(v)); + spa_assert_se(i == t); + } +} + +static void test_lossless_u24(void) +{ + uint32_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = U24_MIN; i < U24_MAX; i+=11) { + float v = U24_TO_F32(u32_to_u24(i)); + uint32_t t = u24_to_u32(F32_TO_U24(v)); + spa_assert_se(i == t); + } +} + +static void test_lossless_s32(void) +{ + int32_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = S32_MIN; i < S32_MAX; i+=255) { + float v = S32_TO_F32(i); + int32_t t = F32_TO_S32(v); + spa_assert_se(SPA_ABS(i - t) <= 128); + } +} + +static void test_lossless_u32(void) +{ + uint32_t i; + + fprintf(stderr, "test %s:\n", __func__); + for (i = U32_MIN; i < U32_MAX; i+=255) { + float v = U32_TO_F32(i); + uint32_t t = F32_TO_U32(v); + spa_assert_se(i > t ? (i - t) <= 128 : (t - i) <= 128); + } +} + +static void test_swaps(void) +{ + { + uint24_t v = U32_TO_U24(0x123456); + uint24_t t = U32_TO_U24(0x563412); + uint24_t s = bswap_u24(v); + spa_assert_se(memcmp(&s, &t, sizeof(t)) == 0); + } + { + int24_t v = S32_TO_S24(0xfffe1dc0); + int24_t t = S32_TO_S24(0xffc01dfe); + int24_t s = bswap_s24(v); + spa_assert_se(memcmp(&s, &t, sizeof(t)) == 0); + } + { + int24_t v = S32_TO_S24(0x123456); + int24_t t = S32_TO_S24(0x563412); + int24_t s = bswap_s24(v); + spa_assert_se(memcmp(&s, &t, sizeof(t)) == 0); + } +} + int main(int argc, char *argv) { cpu_flags = get_cpu_flags(); printf("got get CPU flags %d\n", cpu_flags); + test_f32_s8(); + test_s8_f32(); test_f32_u8(); test_u8_f32(); test_f32_u16(); @@ -487,5 +653,16 @@ test_s24_32_f32(); test_f32_f64(); test_f64_f32(); + + test_lossless_s8(); + test_lossless_u8(); + test_lossless_s16(); + test_lossless_u16(); + test_lossless_s24(); + test_lossless_u24(); + test_lossless_s32(); + test_lossless_u32(); + + test_swaps(); return 0; }
View file
pipewire-0.3.53.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c -> pipewire-0.3.54.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c
Changed
@@ -415,7 +415,7 @@ return this; error: - if (this->aacenc) + if (this && this->aacenc) aacEncClose(&this->aacenc); free(this); errno = -res;
View file
pipewire-0.3.53.tar.gz/spa/plugins/bluez5/a2dp-sink.c -> pipewire-0.3.54.tar.gz/spa/plugins/bluez5/a2dp-sink.c
Changed
@@ -743,7 +743,7 @@ * => timeout = (quantum - max_excess)/quantum * packet_time */ uint64_t max_excess = 2*256; - uint64_t packet_samples = this->frame_count * this->block_size / port->frame_size; + uint64_t packet_samples = (uint64_t)this->frame_count * this->block_size / port->frame_size; uint64_t packet_time = packet_samples * SPA_NSEC_PER_SEC / port->current_format.info.raw.rate; uint64_t quantum = SPA_LIKELY(this->clock) ? this->clock->duration : 0; uint64_t timeout = (quantum > max_excess) ? @@ -843,7 +843,7 @@ prev_time = this->current_time; now_time = this->current_time = this->next_time; - spa_log_debug(this->log, "%p: timeout %"PRIu64" %"PRIu64"", this, + spa_log_debug(this->log, "%p: timer %"PRIu64" %"PRIu64"", this, now_time, now_time - prev_time); if (SPA_LIKELY(this->position)) {
View file
pipewire-0.3.53.tar.gz/spa/plugins/bluez5/a2dp-source.c -> pipewire-0.3.54.tar.gz/spa/plugins/bluez5/a2dp-source.c
Changed
@@ -60,18 +60,16 @@ #undef SPA_LOG_TOPIC_DEFAULT #define SPA_LOG_TOPIC_DEFAULT &log_topic +#include "decode-buffer.h" + #define DEFAULT_CLOCK_NAME "clock.system.monotonic" struct props { - uint32_t min_latency; - uint32_t max_latency; char clock_name64; }; #define FILL_FRAMES 2 #define MAX_BUFFERS 32 -#define MIN_LATENCY 512 -#define MAX_LATENCY 1024 struct buffer { uint32_t id; @@ -89,6 +87,7 @@ uint64_t info_all; struct spa_port_info info; struct spa_io_buffers *io; + struct spa_io_rate_match *rate_match; struct spa_latency_info latency; #define IDX_EnumFormat 0 #define IDX_Meta 1 @@ -105,8 +104,7 @@ struct spa_list free; struct spa_list ready; - struct buffer *current_buffer; - uint32_t ready_offset; + struct spa_bt_decode_buffer buffer; }; struct impl { @@ -120,6 +118,8 @@ struct spa_hook_list hooks; struct spa_callbacks callbacks; + uint32_t quantum_limit; + uint64_t info_all; struct spa_node_info info; #define IDX_PropInfo 0 @@ -137,6 +137,8 @@ unsigned int started:1; unsigned int transport_acquired:1; unsigned int following:1; + unsigned int matching:1; + unsigned int resampling:1; unsigned int is_input:1; unsigned int is_duplex:1; @@ -144,9 +146,15 @@ int fd; struct spa_source source; + struct spa_source timer_source; + int timerfd; + struct spa_io_clock *clock; struct spa_io_position *position; + uint64_t current_time; + uint64_t next_time; + const struct a2dp_codec *codec; bool codec_props_changed; void *codec_props; @@ -154,10 +162,8 @@ struct spa_audio_info codec_format; uint8_t buffer_read4096; - uint8_t buffer_decoded65536; struct timespec now; uint64_t sample_count; - uint64_t skip_count; int duplex_timerfd; uint64_t duplex_timeout; @@ -165,13 +171,8 @@ #define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0) -static const uint32_t default_min_latency = MIN_LATENCY; -static const uint32_t default_max_latency = MAX_LATENCY; - static void reset_props(struct props *props) { - props->min_latency = default_min_latency; - props->max_latency = default_max_latency; strncpy(props->clock_name, DEFAULT_CLOCK_NAME, sizeof(props->clock_name)); } @@ -200,43 +201,19 @@ switch (id) { case SPA_PARAM_PropInfo: { - struct props *p = &this->props; - switch (result.index) { - case 0: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_minLatency), - SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX)); - break; - case 1: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_maxLatency), - SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX)); - break; default: enum_codec = true; - index_offset = 2; + index_offset = 0; } break; } case SPA_PARAM_Props: { - struct props *p = &this->props; - switch (result.index) { - case 0: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_Props, id, - SPA_PROP_minLatency, SPA_POD_Int(p->min_latency), - SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency)); - break; default: enum_codec = true; - index_offset = 1; + index_offset = 0; } break; } @@ -267,13 +244,38 @@ return 0; } -static int do_reassing_follower(struct spa_loop *loop, +static int set_timeout(struct impl *this, uint64_t time) +{ + struct itimerspec ts; + ts.it_value.tv_sec = time / SPA_NSEC_PER_SEC; + ts.it_value.tv_nsec = time % SPA_NSEC_PER_SEC; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + return spa_system_timerfd_settime(this->data_system, + this->timerfd, SPA_FD_TIMER_ABSTIME, &ts, NULL); +} + +static int set_timers(struct impl *this) +{ + struct timespec now; + + spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &now); + this->next_time = SPA_TIMESPEC_TO_NSEC(&now); + + return set_timeout(this, this->following ? 0 : this->next_time); +} + +static int do_reassign_follower(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) { + struct impl *this = user_data; + struct port *port = &this->port; + + spa_bt_decode_buffer_recover(&port->buffer); return 0; } @@ -309,7 +311,7 @@ if (this->started && following != this->following) { spa_log_debug(this->log, "%p: reassign follower %d->%d", this, this->following, following); this->following = following; - spa_loop_invoke(this->data_loop, do_reassing_follower, 0, NULL, 0, true, this); + spa_loop_invoke(this->data_loop, do_reassign_follower, 0, NULL, 0, true, this); } return 0; } @@ -324,10 +326,7 @@ if (param == NULL) { reset_props(&new_props); } else { - spa_pod_parse_object(param, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency)); + /* noop */ } changed = (memcmp(&new_props, &this->props, sizeof(struct props)) != 0); @@ -372,7 +371,6 @@ spa_list_init(&port->free); spa_list_init(&port->ready); - port->current_buffer = NULL; for (i = 0; i < port->n_buffers; i++) { struct buffer *b = &port->buffersi; @@ -449,30 +447,15 @@ return dst_size - avail; } -static void skip_ready_buffers(struct impl *this) -{ - struct port *port = &this->port; - - /* Move all buffers from ready to free */ - while (!spa_list_is_empty(&port->ready)) { - struct buffer *b; - b = spa_list_first(&port->ready, struct buffer, link); - spa_list_remove(&b->link); - spa_list_append(&port->free, &b->link); - spa_assert(!b->outstanding); - this->skip_count += b->buf->datas0.chunk->size / port->frame_size; - } -} - static void a2dp_on_ready_read(struct spa_source *source) { struct impl *this = source->data; struct port *port = &this->port; - struct spa_io_buffers *io = port->io; - int32_t size_read, decoded, avail; - struct spa_data *datas; - struct buffer *buffer; - uint32_t min_data; + struct timespec now; + void *buf; + int32_t size_read, decoded; + uint32_t avail; + uint64_t dt; /* make sure the source is an input */ if ((source->rmask & SPA_IO_IN) == 0) { @@ -486,9 +469,6 @@ spa_log_trace(this->log, "socket poll"); - /* update the current pts */ - spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &this->now); - /* read */ size_read = read_data (this); if (size_read == 0) @@ -497,7 +477,9 @@ spa_log_error(this->log, "failed to read data: %s", spa_strerror(size_read)); goto stop; } - spa_log_trace(this->log, "read socket data %d", size_read); + + /* update the current pts */ + spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &now); if (this->codec_props_changed && this->codec_props && this->codec->update_props) { @@ -505,111 +487,33 @@ this->codec_props_changed = false; } - /* decode */ - decoded = decode_data(this, this->buffer_read, size_read, - this->buffer_decoded, sizeof (this->buffer_decoded)); + /* decode to buffer */ + buf = spa_bt_decode_buffer_get_write(&port->buffer, &avail); + spa_log_trace(this->log, "read socket data size:%d, avail:%d", size_read, avail); + decoded = decode_data(this, this->buffer_read, size_read, buf, avail); if (decoded < 0) { spa_log_debug(this->log, "failed to decode data: %d", decoded); return; } - if (decoded == 0) + if (decoded == 0) { + spa_log_trace(this->log, "no decoded socket data"); return; - - spa_log_trace(this->log, "decoded socket data %d", decoded); + } /* discard when not started */ if (!this->started) return; - /* get buffer */ - if (!port->current_buffer) { - if (spa_list_is_empty(&port->free)) { - /* xrun, skip ahead */ - skip_ready_buffers(this); - this->skip_count += decoded / port->frame_size; - this->sample_count += decoded / port->frame_size; - return; - } - if (this->skip_count > 0) { - spa_log_info(this->log, "%p: xrun, skipped %"PRIu64" usec", - this, (uint64_t)(this->skip_count * SPA_USEC_PER_SEC / port->current_format.info.raw.rate)); - this->skip_count = 0; - } - - buffer = spa_list_first(&port->free, struct buffer, link); - spa_list_remove(&buffer->link); - - port->current_buffer = buffer; - port->ready_offset = 0; - spa_log_trace(this->log, "dequeue %d", buffer->id); - - if (buffer->h) { - buffer->h->seq = this->sample_count; - buffer->h->pts = SPA_TIMESPEC_TO_NSEC(&this->now); - buffer->h->dts_offset = 0; - } - } else { - buffer = port->current_buffer; - } - datas = buffer->buf->datas; - - /* copy data into buffer */ - avail = SPA_MIN(decoded, (int32_t)(datas0.maxsize - port->ready_offset)); - if (avail < decoded) - spa_log_warn(this->log, "buffer too small (%d > %d)", decoded, avail); - memcpy ((uint8_t *)datas0.data + port->ready_offset, this->buffer_decoded, avail); - port->ready_offset += avail; - this->sample_count += decoded / port->frame_size; - - /* send buffer if full */ - min_data = SPA_MIN(this->props.min_latency * port->frame_size, datas0.maxsize / 2); - if (port->ready_offset >= min_data) { - uint64_t sample_count; - - datas0.chunk->offset = 0; - datas0.chunk->size = port->ready_offset; - datas0.chunk->stride = port->frame_size; - - sample_count = datas0.chunk->size / port->frame_size; - - spa_log_trace(this->log, "queue %d", buffer->id); - spa_list_append(&port->ready, &buffer->link); - port->current_buffer = NULL; - - if (!this->following && this->clock) { - this->clock->nsec = SPA_TIMESPEC_TO_NSEC(&this->now); - this->clock->duration = sample_count * this->clock->rate.denom / port->current_format.info.raw.rate; - this->clock->position = this->sample_count * this->clock->rate.denom / port->current_format.info.raw.rate; - this->clock->delay = 0; - this->clock->rate_diff = 1.0f; - this->clock->next_nsec = this->clock->nsec + (uint64_t)sample_count * SPA_NSEC_PER_SEC / port->current_format.info.raw.rate; - } - } - - /* done if there are no buffers ready */ - if (spa_list_is_empty(&port->ready)) - return; - - if (this->following) - return; - - /* process the buffer if IO does not have any */ - if (io != NULL && io->status != SPA_STATUS_HAVE_DATA) { - struct buffer *b; - - if (io->buffer_id < port->n_buffers) - recycle_buffer(this, port, io->buffer_id); + spa_bt_decode_buffer_write_packet(&port->buffer, decoded); - b = spa_list_first(&port->ready, struct buffer, link); - spa_list_remove(&b->link); - b->outstanding = true; + dt = SPA_TIMESPEC_TO_NSEC(&this->now); + this->now = now; + dt = SPA_TIMESPEC_TO_NSEC(&this->now) - dt; - io->buffer_id = b->id; - io->status = SPA_STATUS_HAVE_DATA; - } + spa_log_trace(this->log, "decoded socket data size:%d frames:%d dt:%d dms", + (int)decoded, (int)decoded/port->frame_size, + (int)(dt / 100000)); - /* notify ready */ - spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA); return; stop: @@ -641,6 +545,75 @@ a2dp_on_ready_read(source); } +static int setup_matching(struct impl *this) +{ + struct port *port = &this->port; + + if (this->position && port->rate_match) { + port->rate_match->rate = 1 / port->buffer.corr; + + this->matching = this->following; + this->resampling = this->matching || + (port->current_format.info.raw.rate != this->position->clock.rate.denom); + } else { + this->matching = false; + this->resampling = false; + } + + if (port->rate_match) + SPA_FLAG_UPDATE(port->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE, this->matching); + + return 0; +} + +static void a2dp_on_timeout(struct spa_source *source) +{ + struct impl *this = source->data; + struct port *port = &this->port; + uint64_t exp, duration; + uint32_t rate; + struct spa_io_buffers *io = port->io; + uint64_t prev_time, now_time; + + if (this->transport == NULL) + return; + + if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0) + spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno)); + + prev_time = this->current_time; + now_time = this->current_time = this->next_time; + + spa_log_trace(this->log, "%p: timer %"PRIu64" %"PRIu64"", this, + now_time, now_time - prev_time); + + if (SPA_LIKELY(this->position)) { + duration = this->position->clock.duration; + rate = this->position->clock.rate.denom; + } else { + duration = 1024; + rate = 48000; + } + + setup_matching(this); + + this->next_time = now_time + duration * SPA_NSEC_PER_SEC / port->buffer.corr / rate; + + if (SPA_LIKELY(this->clock)) { + this->clock->nsec = now_time; + this->clock->position += duration; + this->clock->duration = duration; + this->clock->rate_diff = port->buffer.corr; + this->clock->next_nsec = this->next_time; + } + + spa_log_trace(this->log, "%p: %d", this, io->status); + io->status = SPA_STATUS_HAVE_DATA; + spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA); + + set_timeout(this, this->next_time); +} + static int transport_start(struct impl *this) { int res, val; @@ -683,7 +656,13 @@ if (setsockopt(this->transport->fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0) spa_log_warn(this->log, "SO_PRIORITY failed: %m"); - reset_buffers(&this->port); + reset_buffers(port); + + spa_bt_decode_buffer_clear(&port->buffer); + if ((res = spa_bt_decode_buffer_init(&port->buffer, this->log, + port->frame_size, port->current_format.info.raw.rate, + this->quantum_limit, this->quantum_limit)) < 0) + return res; this->fd = this->transport->fd; @@ -716,8 +695,18 @@ set_duplex_timeout(this, this->duplex_timeout); } + this->timer_source.data = this; + this->timer_source.fd = this->timerfd; + this->timer_source.func = a2dp_on_timeout; + this->timer_source.mask = SPA_IO_IN; + this->timer_source.rmask = 0; + spa_loop_add_source(this->data_loop, &this->timer_source); + this->sample_count = 0; - this->skip_count = 0; + + setup_matching(this); + + set_timers(this); return 0; } @@ -753,6 +742,7 @@ void *user_data) { struct impl *this = user_data; + struct itimerspec ts; spa_log_debug(this->log, "%p: remove source", this); @@ -761,11 +751,20 @@ if (this->source.loop) spa_loop_remove_source(this->data_loop, &this->source); + if (this->timer_source.loop) + spa_loop_remove_source(this->data_loop, &this->timer_source); + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = 0; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + spa_system_timerfd_settime(this->data_system, this->timerfd, 0, &ts, NULL); + return 0; } static int transport_stop(struct impl *this) { + struct port *port = &this->port; int res; spa_log_debug(this->log, "%p: transport stop", this); @@ -783,6 +782,8 @@ this->codec->deinit(this->codec_data); this->codec_data = NULL; + spa_bt_decode_buffer_clear(&port->buffer); + return res; } @@ -836,24 +837,20 @@ static void emit_node_info(struct impl *this, bool full) { - char latency64 = SPA_STRINGIFY(MIN_LATENCY)"/48000"; uint64_t old = full ? this->info.change_mask : 0; struct spa_dict_item node_info_items = { { SPA_KEY_DEVICE_API, "bluez5" }, { SPA_KEY_MEDIA_CLASS, this->is_input ? "Audio/Source" : "Stream/Output/Audio" }, - { SPA_KEY_NODE_LATENCY, latency }, + { SPA_KEY_NODE_LATENCY, this->is_input ? "" : "512/48000" }, { "media.name", ((this->transport && this->transport->device->name) ? - this->transport->device->name : "A2DP") }, - { SPA_KEY_NODE_DRIVER, this->is_input ? "true" : "false" }, + this->transport->device->name : "A2DP") }, + { SPA_KEY_NODE_DRIVER, this->is_input ? "true" : "false" }, }; if (full) this->info.change_mask = this->info_all; if (this->info.change_mask) { - if (this->transport && this->port.have_format) - snprintf(latency, sizeof(latency), "%d/%d", (int)this->props.min_latency, - (int)this->port.current_format.info.raw.rate); this->info.props = &SPA_DICT_INIT_ARRAY(node_info_items); spa_node_emit_info(&this->hooks, &this->info); this->info.change_mask = old; @@ -991,11 +988,11 @@ param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_ParamBuffers, id, - SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 8, MAX_BUFFERS), + SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - this->props.max_latency * port->frame_size, - this->props.min_latency * port->frame_size, + this->quantum_limit * port->frame_size, + 16 * port->frame_size, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->frame_size)); break; @@ -1021,6 +1018,12 @@ SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Buffers), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_buffers))); break; + case 1: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_ParamIO, id, + SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_RateMatch), + SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_rate_match))); + break; default: return 0; } @@ -1059,7 +1062,6 @@ spa_list_init(&port->ready); port->n_buffers = 0; } - port->current_buffer = NULL; return 0; } @@ -1217,6 +1219,9 @@ case SPA_IO_Buffers: port->io = data; break; + case SPA_IO_RateMatch: + port->rate_match = data; + break; default: return -ENOENT; } @@ -1244,6 +1249,88 @@ return 0; } +static uint32_t get_samples(struct impl *this, uint32_t *duration) +{ + struct port *port = &this->port; + uint32_t samples; + + if (SPA_LIKELY(port->rate_match) && this->resampling) { + samples = port->rate_match->size; + } else { + if (SPA_LIKELY(this->position)) + samples = this->position->clock.duration * port->current_format.info.raw.rate + / this->position->clock.rate.denom; + else + samples = 1024; + } + + if (SPA_LIKELY(this->position)) + *duration = this->position->clock.duration * port->current_format.info.raw.rate + / this->position->clock.rate.denom; + else if (SPA_LIKELY(this->clock)) + *duration = this->clock->duration * port->current_format.info.raw.rate + / this->clock->rate.denom; + else + *duration = 1024 * port->current_format.info.raw.rate / 48000; + + return samples; +} + +static void process_buffering(struct impl *this) +{ + struct port *port = &this->port; + uint32_t duration; + const uint32_t samples = get_samples(this, &duration); + uint32_t avail; + void *buf; + + spa_bt_decode_buffer_process(&port->buffer, samples, duration); + + setup_matching(this); + + buf = spa_bt_decode_buffer_get_read(&port->buffer, &avail); + + /* copy data to buffers */ + if (!spa_list_is_empty(&port->free) && avail > 0) { + struct buffer *buffer; + struct spa_data *datas; + uint32_t data_size; + + data_size = samples * port->frame_size; + + avail = SPA_MIN(avail, data_size); + + spa_bt_decode_buffer_read(&port->buffer, avail); + + buffer = spa_list_first(&port->free, struct buffer, link); + spa_list_remove(&buffer->link); + + spa_log_trace(this->log, "dequeue %d", buffer->id); + + if (buffer->h) { + buffer->h->seq = this->sample_count; + buffer->h->pts = SPA_TIMESPEC_TO_NSEC(&this->now); + buffer->h->dts_offset = 0; + } + + datas = buffer->buf->datas; + + spa_assert(datas0.maxsize >= data_size); + + datas0.chunk->offset = 0; + datas0.chunk->size = avail; + datas0.chunk->stride = port->frame_size; + + memcpy(datas0.data, buf, avail); + + this->sample_count += avail / port->frame_size; + + /* ready buffer if full */ + spa_log_trace(this->log, "queue %d frames:%d", buffer->id, (int)avail / port->frame_size); + spa_list_append(&port->ready, &buffer->link); + } +} + static int impl_node_process(void *object) { struct impl *this = object; @@ -1269,6 +1356,9 @@ io->buffer_id = SPA_ID_INVALID; } + /* Handle buffering delay */ + process_buffering(this); + /* Return if there are no buffers ready to be processed */ if (spa_list_is_empty(&port->ready)) return SPA_STATUS_OK; @@ -1350,16 +1440,19 @@ static int impl_clear(struct spa_handle *handle) { struct impl *this = (struct impl *) handle; + struct port *port = &this->port; if (this->codec_data) this->codec->deinit(this->codec_data); if (this->codec_props && this->codec->clear_props) this->codec->clear_props(this->codec_props); if (this->transport) spa_hook_remove(&this->transport_listener); + spa_system_close(this->data_system, this->timerfd); if (this->duplex_timerfd >= 0) { spa_system_close(this->data_system, this->duplex_timerfd); this->duplex_timerfd = -1; } + spa_bt_decode_buffer_clear(&port->buffer); return 0; } @@ -1451,7 +1544,11 @@ spa_list_init(&port->ready); spa_list_init(&port->free); + this->quantum_limit = 8192; + if (info != NULL) { + if (info && (str = spa_dict_lookup(info, "clock.quantum-limit"))) + spa_atou32(str, &this->quantum_limit, 0); if ((str = spa_dict_lookup(info, SPA_KEY_API_BLUEZ5_TRANSPORT)) != NULL) sscanf(str, "pointer:%p", &this->transport); if ((str = spa_dict_lookup(info, "bluez5.a2dp-source-role")) != NULL) @@ -1486,6 +1583,9 @@ spa_bt_transport_add_listener(this->transport, &this->transport_listener, &transport_events, this); + this->timerfd = spa_system_timerfd_create(this->data_system, + CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + if (this->is_duplex) { this->duplex_timerfd = spa_system_timerfd_create(this->data_system, CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK);
View file
pipewire-0.3.53.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.54.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -3293,18 +3293,20 @@ ret = a2dp_codec_to_endpoint(codec, endpoint, &object_path); if (ret < 0) - return ret; + goto error; - caps_size = codec->fill_caps(codec, 0, caps); - if (caps_size < 0) - return caps_size; + ret = caps_size = codec->fill_caps(codec, 0, caps); + if (ret < 0) + goto error; m = dbus_message_new_method_call(BLUEZ_SERVICE, path, BLUEZ_MEDIA_INTERFACE, "RegisterEndpoint"); - if (m == NULL) - return -EIO; + if (m == NULL) { + ret = -EIO; + goto error; + } dbus_message_iter_init_append(m, &object_it); dbus_message_iter_append_basic(&object_it, DBUS_TYPE_OBJECT_PATH, &object_path); @@ -3327,6 +3329,10 @@ free(object_path); return 0; + +error: + free(object_path); + return ret; } static int register_a2dp_endpoint(struct spa_bt_monitor *monitor,
View file
pipewire-0.3.54.tar.gz/spa/plugins/bluez5/decode-buffer.h
Added
@@ -0,0 +1,381 @@ +/* Spa Bluez5 decode buffer + * + * Copyright © 2022 Pauli Virtanen + * + * 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. + */ + +/** + * \file decode-buffer.h Buffering for Bluetooth sources + * + * A linear buffer, which is compacted when it gets half full. + * + * Also contains buffering logic, which calculates a rate correction + * factor to maintain the buffer level at the target value. + * + * Consider typical packet intervals with nominal frame duration + * of 10ms: + * + * ... 5ms | 5ms | 20ms | 5ms | 5ms | 20ms ... + * + * ... 3ms | 3ms | 4ms | 30ms | 3ms | 3ms | 4ms | 30ms ... + * + * plus random jitter; 10ms nominal may occasionally have 20+ms interval. + * The regular timer cycle cannot be aligned with this, so process() + * may occur at any time. + * + * The buffer level is the difference between the number of samples in + * buffer immediately after receiving a packet, and the samples consumed + * before receiving the next packet. + * + * The buffer level indicates how much any packet can be delayed without + * underrun. If it is positive, there are no underruns. + * + * The rate correction aims to maintain the average level at a safety margin. + */ + +#ifndef SPA_BLUEZ5_DECODE_BUFFER_H +#define SPA_BLUEZ5_DECODE_BUFFER_H + +#include <stdlib.h> +#include <spa/utils/defs.h> +#include <spa/utils/dll.h> +#include <spa/support/log.h> + +#define BUFFERING_LONG_MSEC 60000 +#define BUFFERING_SHORT_MSEC 1000 +#define BUFFERING_DLL_BW 0.03 +#define BUFFERING_RATE_DIFF_MAX 0.005 + +/** + * Safety margin. + * + * The spike is the long-window maximum difference + * between minimum and average buffer level. + */ +#define BUFFERING_TARGET(spike,packet_size) \ + SPA_CLAMP((spike)*3/2, (packet_size), 6*(packet_size)) + +/** Windowed min/max */ +struct spa_bt_ptp +{ + union { + int32_t min; + int32_t mins4; + }; + union { + int32_t max; + int32_t maxs4; + }; + uint32_t pos; + uint32_t period; +}; + +struct spa_bt_decode_buffer +{ + struct spa_log *log; + + uint32_t frame_size; + uint32_t rate; + + uint8_t *buffer_decoded; + uint32_t buffer_size; + uint32_t buffer_reserve; + uint32_t write_index; + uint32_t read_index; + + struct spa_bt_ptp spike; /**< spikes (long window) */ + struct spa_bt_ptp packet_size; /**< packet size (short window) */ + + int32_t target; + int32_t level; + double level_avg; + + struct spa_dll dll; + double corr; + + uint32_t prev_consumed; + uint32_t prev_avail; + uint32_t prev_duration; + uint32_t underrun; + uint32_t pos; + + uint8_t received:1; + uint8_t buffering:1; +}; + +static void spa_bt_ptp_init(struct spa_bt_ptp *p, int32_t period) +{ + size_t i; + + spa_zero(*p); + for (i = 0; i < SPA_N_ELEMENTS(p->mins); ++i) { + p->minsi = INT32_MAX; + p->maxsi = INT32_MIN; + } + p->period = period; +} + +static void spa_bt_ptp_update(struct spa_bt_ptp *p, int32_t value, uint32_t duration) +{ + const size_t n = SPA_N_ELEMENTS(p->mins); + size_t i; + + for (i = 0; i < n; ++i) { + p->minsi = SPA_MIN(p->minsi, value); + p->maxsi = SPA_MAX(p->maxsi, value); + } + + p->pos += duration; + if (p->pos >= p->period / (n - 1)) { + p->pos = 0; + for (i = 1; i < SPA_N_ELEMENTS(p->mins); ++i) { + p->minsi-1 = p->minsi; + p->maxsi-1 = p->maxsi; + } + p->minsn-1 = INT32_MAX; + p->maxsn-1 = INT32_MIN; + } +} + +static int spa_bt_decode_buffer_init(struct spa_bt_decode_buffer *this, struct spa_log *log, + uint32_t frame_size, uint32_t rate, uint32_t quantum_limit, uint32_t reserve) +{ + spa_zero(*this); + this->frame_size = frame_size; + this->rate = rate; + this->log = log; + this->buffer_reserve = this->frame_size * reserve; + this->buffer_size = this->frame_size * quantum_limit * 2; + this->buffer_size += this->buffer_reserve; + this->corr = 1.0; + this->buffering = true; + + spa_dll_init(&this->dll); + + spa_bt_ptp_init(&this->spike, (uint64_t)this->rate * BUFFERING_LONG_MSEC / 1000); + spa_bt_ptp_init(&this->packet_size, (uint64_t)this->rate * BUFFERING_SHORT_MSEC / 1000); + + if ((this->buffer_decoded = malloc(this->buffer_size)) == NULL) { + this->buffer_size = 0; + return -ENOMEM; + } + return 0; +} + +static void spa_bt_decode_buffer_clear(struct spa_bt_decode_buffer *this) +{ + free(this->buffer_decoded); + spa_zero(*this); +} + +static void spa_bt_decode_buffer_compact(struct spa_bt_decode_buffer *this) +{ + uint32_t avail; + + spa_assert(this->read_index <= this->write_index); + + if (this->read_index == this->write_index) { + this->read_index = 0; + this->write_index = 0; + goto done; + } + + if (this->write_index > this->read_index + this->buffer_size - this->buffer_reserve) { + /* Drop data to keep buffer reserve free */ + spa_log_info(this->log, "%p buffer overrun: dropping data", this); + this->read_index = this->write_index + this->buffer_reserve - this->buffer_size; + } + + if (this->write_index < (this->buffer_size - this->buffer_reserve) / 2 + || this->read_index == 0) + goto done; + + avail = this->write_index - this->read_index; + spa_memmove(this->buffer_decoded, + SPA_PTROFF(this->buffer_decoded, this->read_index, void), + avail); + this->read_index = 0; + this->write_index = avail; + +done: + spa_assert(this->buffer_size - this->write_index >= this->buffer_reserve); +} + +static void *spa_bt_decode_buffer_get_write(struct spa_bt_decode_buffer *this, uint32_t *avail) +{ + spa_bt_decode_buffer_compact(this); + spa_assert(this->buffer_size >= this->write_index); + *avail = this->buffer_size - this->write_index; + return SPA_PTROFF(this->buffer_decoded, this->write_index, void); +} + +static void spa_bt_decode_buffer_write_packet(struct spa_bt_decode_buffer *this, uint32_t size) +{ + spa_assert(size % this->frame_size == 0); + this->write_index += size; + this->received = true; + spa_bt_ptp_update(&this->packet_size, size / this->frame_size, size / this->frame_size); +} + +static void *spa_bt_decode_buffer_get_read(struct spa_bt_decode_buffer *this, uint32_t *avail) +{ + spa_assert(this->write_index >= this->read_index); + if (!this->buffering) + *avail = this->write_index - this->read_index; + else + *avail = 0; + return SPA_PTROFF(this->buffer_decoded, this->read_index, void); +} + +static void spa_bt_decode_buffer_read(struct spa_bt_decode_buffer *this, uint32_t size) +{ + spa_assert(size % this->frame_size == 0); + this->read_index += size; +} + +static void spa_bt_decode_buffer_recover(struct spa_bt_decode_buffer *this) +{ + int32_t size = (this->write_index - this->read_index) / this->frame_size; + + this->prev_avail = size * this->frame_size; + this->prev_consumed = this->prev_duration; + this->level = (int32_t)this->prev_avail/this->frame_size + - (int32_t)this->prev_duration; + this->level_avg = this->level; + this->target = this->level; + this->corr = 1.0; + + spa_dll_init(&this->dll); +} + +static void spa_bt_decode_buffer_process(struct spa_bt_decode_buffer *this, uint32_t samples, uint32_t duration) +{ + const uint32_t data_size = samples * this->frame_size; + const int32_t max_level = SPA_MAX(8 * this->packet_size.max, (int32_t)duration); + uint32_t avail; + + if (SPA_UNLIKELY(duration != this->prev_duration)) { + this->prev_duration = duration; + spa_bt_decode_buffer_recover(this); + } + + if (SPA_UNLIKELY(this->buffering)) { + int32_t size = (this->write_index - this->read_index) / this->frame_size; + + this->corr = 1.0; + + spa_log_trace(this->log, "%p buffering size:%d", this, (int)size); + + if (this->received && + this->packet_size.max > 0 && + size >= SPA_MAX(3*this->packet_size.max, (int32_t)duration)) + this->buffering = false; + else + return; + + spa_bt_decode_buffer_recover(this); + } + + if (SPA_UNLIKELY(this->dll.bw == 0.0)) { + spa_log_trace(this->log, "%p dll reset duration:%d rate:%d", this, + (int)duration, (int)this->rate); + spa_dll_set_bw(&this->dll, BUFFERING_DLL_BW, duration, (uint64_t)this->rate); + } + + spa_bt_decode_buffer_get_read(this, &avail); + + if (this->received) { + const uint32_t avg_period = (uint64_t)this->rate * BUFFERING_SHORT_MSEC / 1000; + int32_t level, target; + + /* Track buffer level */ + level = (int32_t)(this->prev_avail/this->frame_size) - (int32_t)this->prev_consumed; + level = SPA_MAX(level, -max_level); + this->prev_consumed = SPA_MIN(this->prev_consumed, avg_period); + + this->level_avg = ((double)this->prev_consumed*level + + ((double)avg_period - this->prev_consumed)*this->level_avg) / avg_period; + spa_bt_ptp_update(&this->spike, this->level_avg - level, this->prev_consumed); + + /* Update target level */ + target = BUFFERING_TARGET(this->spike.max, this->packet_size.max); + + if (level > SPA_MAX(4 * target, 2*(int32_t)duration) && + avail > data_size) { + /* Lagging too much: drop data */ + uint32_t size = SPA_MIN(avail - data_size, + (level - target*5/2) * this->frame_size); + + spa_bt_decode_buffer_read(this, size); + spa_log_trace(this->log, "%p overrun samples:%d level:%d target:%d", + this, (int)size/this->frame_size, + (int)level, (int)target); + + spa_bt_decode_buffer_recover(this); + } + + this->pos += this->prev_consumed; + if (this->pos > this->rate) { + spa_log_debug(this->log, + "%p avg:%d target:%d level:%d buffer:%d spike:%d corr:%f", + this, + (int)this->level_avg, + (int)target, + (int)level, + (int)(avail / this->frame_size), + (int)this->spike.max, + (double)this->corr); + this->pos = 0; + } + + spa_bt_decode_buffer_get_read(this, &avail); + + this->prev_consumed = 0; + this->prev_avail = avail; + this->underrun = 0; + this->received = false; + this->level = level; + this->target = target; + } + + this->corr = spa_dll_update(&this->dll, this->target - this->level); + + if (SPA_ABS(this->corr - 1.0) > BUFFERING_RATE_DIFF_MAX) { + spa_log_trace(this->log, "%p too big rate difference: clamp + reset", this); + spa_dll_init(&this->dll); + this->corr = SPA_CLAMP(this->corr, 1.0 - BUFFERING_RATE_DIFF_MAX, + 1.0 + BUFFERING_RATE_DIFF_MAX); + } + + if (avail < data_size) { + spa_log_trace(this->log, "%p underrun samples:%d", this, + (data_size - avail) / this->frame_size); + this->underrun += samples; + if (this->underrun >= SPA_MIN((uint32_t)max_level, this->buffer_size / this->frame_size)) { + this->buffering = true; + spa_log_debug(this->log, "%p underrun too much: start buffering", this); + } + } + + this->prev_consumed += samples; +} + +#endif
View file
pipewire-0.3.53.tar.gz/spa/plugins/bluez5/sco-io.c -> pipewire-0.3.54.tar.gz/spa/plugins/bluez5/sco-io.c
Changed
@@ -55,16 +55,12 @@ * since kernel might not report it as the socket MTU, see * https://lore.kernel.org/linux-bluetooth/20201210003528.3pmaxvubiwegxmhl@pali/T/ * - * Since 24 is the packet size for the smallest setting (ALT1), we'll stop - * reading when rx packet of at least this size is seen, and use its size as the - * heuristic maximum write MTU. Of course, if we have a source connected, we'll - * continue reading without stopping. + * We continue reading also when there's no source connected, to keep socket + * flushed. * * XXX: when the kernel/backends start giving the right values, the heuristic * XXX: can be removed */ -#define HEURISTIC_MIN_MTU 24 - #define MAX_MTU 1024 @@ -94,12 +90,6 @@ int enabled; int changed = 0; - enabled = io->source_cb != NULL || io->read_size < HEURISTIC_MIN_MTU; - if (SPA_FLAG_IS_SET(io->source.mask, SPA_IO_IN) != enabled) { - SPA_FLAG_UPDATE(io->source.mask, SPA_IO_IN, enabled); - changed = 1; - } - enabled = io->sink_cb != NULL; if (SPA_FLAG_IS_SET(io->source.mask, SPA_IO_OUT) != enabled) { SPA_FLAG_UPDATE(io->source.mask, SPA_IO_OUT, enabled); @@ -118,11 +108,6 @@ if (SPA_FLAG_IS_SET(source->rmask, SPA_IO_IN)) { int res; - /* - * Note that we will read from the socket for a few times even - * when there is no source callback, to autodetect packet size. - */ - read_again: res = read(io->fd, io->read_buffer, SPA_MIN(io->read_mtu, MAX_MTU)); if (res <= 0) {
View file
pipewire-0.3.53.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.54.tar.gz/spa/plugins/bluez5/sco-source.c
Changed
@@ -58,11 +58,11 @@ #undef SPA_LOG_TOPIC_DEFAULT #define SPA_LOG_TOPIC_DEFAULT &log_topic +#include "decode-buffer.h" + #define DEFAULT_CLOCK_NAME "clock.system.monotonic" struct props { - uint32_t min_latency; - uint32_t max_latency; char clock_name64; }; @@ -101,8 +101,7 @@ struct spa_list free; struct spa_list ready; - struct buffer *current_buffer; - uint32_t ready_offset; + struct spa_bt_decode_buffer buffer; }; struct impl { @@ -116,6 +115,8 @@ struct spa_hook_list hooks; struct spa_callbacks callbacks; + uint32_t quantum_limit; + uint64_t info_all; struct spa_node_info info; #define IDX_PropInfo 0 @@ -132,10 +133,18 @@ unsigned int started:1; unsigned int following:1; + unsigned int matching:1; + unsigned int resampling:1; + + struct spa_source timer_source; + int timerfd; struct spa_io_clock *clock; struct spa_io_position *position; + uint64_t current_time; + uint64_t next_time; + /* mSBC */ sbc_t msbc; bool msbc_seq_initialized; @@ -150,13 +159,8 @@ #define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0) -static const uint32_t default_min_latency = 128; -static const uint32_t default_max_latency = 512; - static void reset_props(struct props *props) { - props->min_latency = default_min_latency; - props->max_latency = default_max_latency; strncpy(props->clock_name, DEFAULT_CLOCK_NAME, sizeof(props->clock_name)); } @@ -184,23 +188,7 @@ switch (id) { case SPA_PARAM_PropInfo: { - struct props *p = &this->props; - switch (result.index) { - case 0: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_minLatency), - SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX)); - break; - case 1: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_maxLatency), - SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX)); - break; default: return 0; } @@ -208,15 +196,7 @@ } case SPA_PARAM_Props: { - struct props *p = &this->props; - switch (result.index) { - case 0: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_Props, id, - SPA_PROP_minLatency, SPA_POD_Int(p->min_latency), - SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency)); - break; default: return 0; } @@ -237,6 +217,41 @@ return 0; } +static int set_timeout(struct impl *this, uint64_t time) +{ + struct itimerspec ts; + ts.it_value.tv_sec = time / SPA_NSEC_PER_SEC; + ts.it_value.tv_nsec = time % SPA_NSEC_PER_SEC; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + return spa_system_timerfd_settime(this->data_system, + this->timerfd, SPA_FD_TIMER_ABSTIME, &ts, NULL); +} + +static int set_timers(struct impl *this) +{ + struct timespec now; + + spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &now); + this->next_time = SPA_TIMESPEC_TO_NSEC(&now); + + return set_timeout(this, this->following ? 0 : this->next_time); +} + +static int do_reassign_follower(struct spa_loop *loop, + bool async, + uint32_t seq, + const void *data, + size_t size, + void *user_data) +{ + struct impl *this = user_data; + struct port *port = &this->port; + + spa_bt_decode_buffer_recover(&port->buffer); + return 0; +} + static inline bool is_following(struct impl *this) { return this->position && this->clock && this->position->clock.id != this->clock->id; @@ -269,6 +284,7 @@ if (this->started && following != this->following) { spa_log_debug(this->log, "%p: reassign follower %d->%d", this, this->following, following); this->following = following; + spa_loop_invoke(this->data_loop, do_reassign_follower, 0, NULL, 0, true, this); } return 0; @@ -284,10 +300,7 @@ if (param == NULL) { reset_props(&new_props); } else { - spa_pod_parse_object(param, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency)); + /* noop */ } changed = (memcmp(&new_props, &this->props, sizeof(struct props)) != 0); @@ -326,8 +339,6 @@ spa_list_init(&port->free); spa_list_init(&port->ready); - port->current_buffer = NULL; - for (i = 0; i < port->n_buffers; i++) { struct buffer *b = &port->buffersi; spa_list_append(&port->free, &b->link); @@ -422,116 +433,107 @@ return true; } -static void preprocess_and_decode_msbc_data(void *userdata, uint8_t *read_data, int size_read) +static uint32_t preprocess_and_decode_msbc_data(void *userdata, uint8_t *read_data, int size_read) { struct impl *this = userdata; struct port *port = &this->port; - struct spa_data *datas = port->current_buffer->buf->datas; + uint32_t decoded = 0; + int i; spa_log_trace(this->log, "handling mSBC data"); - /* check if the packet contains only zeros - if so ignore the packet. - This is necessary, because some kernels insert bogus "all-zero" packets - into the datastream. - See https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/549 */ - if (is_zero_packet(read_data, size_read)) { - return; - } + /* + * Check if the packet contains only zeros - if so ignore the packet. + * This is necessary, because some kernels insert bogus "all-zero" packets + * into the datastream. + * See https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/549 + */ + if (is_zero_packet(read_data, size_read)) + return 0; - int i; for (i = 0; i < size_read; ++i) { + void *buf; + uint32_t avail; + int seq, processed; + size_t written; + msbc_buffer_append_byte(this, read_datai); - /* Handle found mSBC packets. - * - * XXX: if there's no space for the decoded audio in - * XXX: the current buffer, we'll drop data. + if (this->msbc_buffer_pos != MSBC_ENCODED_SIZE) + continue; + + /* + * Handle found mSBC packet */ - if (this->msbc_buffer_pos == MSBC_ENCODED_SIZE) { - spa_log_trace(this->log, "Received full mSBC packet, start processing it"); - - if (port->ready_offset + MSBC_DECODED_SIZE <= datas0.maxsize) { - int seq, processed; - size_t written; - spa_log_trace(this->log, - "Output buffer has space, processing mSBC packet"); - - /* Check sequence number */ - seq = ((this->msbc_buffer1 >> 4) & 1) | - ((this->msbc_buffer1 >> 6) & 2); - - spa_log_trace(this->log, "mSBC packet seq=%u", seq); - if (!this->msbc_seq_initialized) { - this->msbc_seq_initialized = true; - this->msbc_seq = seq; - } else if (seq != this->msbc_seq) { - spa_log_info(this->log, - "missing mSBC packet: %u != %u", seq, this->msbc_seq); - this->msbc_seq = seq; - /* TODO: Implement PLC. */ - } - this->msbc_seq = (this->msbc_seq + 1) % 4; - - /* decode frame */ - processed = sbc_decode( - &this->msbc, this->msbc_buffer + 2, MSBC_ENCODED_SIZE - 3, - (uint8_t *)datas0.data + port->ready_offset, MSBC_DECODED_SIZE, - &written); - - if (processed < 0) { - spa_log_warn(this->log, "sbc_decode failed: %d", processed); - /* TODO: manage errors */ - continue; - } - - port->ready_offset += written; - - } else { - spa_log_warn(this->log, "Output buffer full, dropping mSBC packet"); - } + + buf = spa_bt_decode_buffer_get_write(&port->buffer, &avail); + + /* Check sequence number */ + seq = ((this->msbc_buffer1 >> 4) & 1) | + ((this->msbc_buffer1 >> 6) & 2); + + spa_log_trace(this->log, "mSBC packet seq=%u", seq); + if (!this->msbc_seq_initialized) { + this->msbc_seq_initialized = true; + this->msbc_seq = seq; + } else if (seq != this->msbc_seq) { + /* TODO: PLC (too late to insert data now) */ + spa_log_info(this->log, + "missing mSBC packet: %u != %u", seq, this->msbc_seq); + this->msbc_seq = seq; } + + this->msbc_seq = (this->msbc_seq + 1) % 4; + + if (avail < MSBC_DECODED_SIZE) + spa_log_warn(this->log, "Output buffer full, dropping msbc data"); + + /* decode frame */ + processed = sbc_decode( + &this->msbc, this->msbc_buffer + 2, MSBC_ENCODED_SIZE - 3, + buf, avail, &written); + + if (processed < 0) { + spa_log_warn(this->log, "sbc_decode failed: %d", processed); + /* TODO: manage errors */ + continue; + } + + spa_bt_decode_buffer_write_packet(&port->buffer, written); + decoded += written; } + + return decoded; } static int sco_source_cb(void *userdata, uint8_t *read_data, int size_read) { struct impl *this = userdata; struct port *port = &this->port; - struct spa_io_buffers *io = port->io; - struct spa_data *datas; - uint32_t min_data; + uint32_t decoded; + uint64_t dt; if (this->transport == NULL) { spa_log_debug(this->log, "no transport, stop reading"); goto stop; } - /* get buffer */ - if (!port->current_buffer) { - if (spa_list_is_empty(&port->free)) { - spa_log_warn(this->log, "buffer not available"); - return 0; - } - port->current_buffer = spa_list_first(&port->free, struct buffer, link); - spa_list_remove(&port->current_buffer->link); - port->ready_offset = 0; - } - datas = port->current_buffer->buf->datas; - /* update the current pts */ + dt = SPA_TIMESPEC_TO_NSEC(&this->now); spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &this->now); + dt = SPA_TIMESPEC_TO_NSEC(&this->now) - dt; /* handle data read from socket */ - spa_log_trace(this->log, "read socket data %d", size_read); #if 0 hexdump_to_log(this, read_data, size_read); #endif if (this->transport->codec == HFP_AUDIO_CODEC_MSBC) { - preprocess_and_decode_msbc_data(userdata, read_data, size_read); - + decoded = preprocess_and_decode_msbc_data(userdata, read_data, size_read); } else { + uint32_t avail; uint8_t *packet; + if (size_read != 48 && is_zero_packet(read_data, size_read)) { /* Adapter is returning non-standard CVSD stream. For example * Intel 8087:0029 at Firmware revision 0.0 build 191 week 21 2021 @@ -539,62 +541,92 @@ */ return 0; } - packet = (uint8_t *)datas0.data + port->ready_offset; - spa_memmove(packet, read_data, size_read); - port->ready_offset += size_read; + + packet = spa_bt_decode_buffer_get_write(&port->buffer, &avail); + avail = SPA_MIN(avail, (uint32_t)size_read); + spa_memmove(packet, read_data, avail); + spa_bt_decode_buffer_write_packet(&port->buffer, avail); + + decoded = avail; } - /* send buffer if full */ - min_data = SPA_MIN(this->props.min_latency * port->frame_size, datas0.maxsize / 2); - if (port->ready_offset >= min_data) { - uint64_t sample_count; + spa_log_trace(this->log, "read socket data size:%d decoded frames:%d dt:%d dms", + size_read, decoded / port->frame_size, + (int)(dt / 100000)); - datas0.chunk->offset = 0; - datas0.chunk->size = port->ready_offset; - datas0.chunk->stride = port->frame_size; + return 0; - sample_count = datas0.chunk->size / port->frame_size; - spa_list_append(&port->ready, &port->current_buffer->link); - port->current_buffer = NULL; - - if (!this->following && this->clock) { - this->clock->nsec = SPA_TIMESPEC_TO_NSEC(&this->now); - this->clock->duration = sample_count * this->clock->rate.denom / port->current_format.info.raw.rate; - this->clock->position += this->clock->duration; - this->clock->delay = 0; - this->clock->rate_diff = 1.0f; - this->clock->next_nsec = this->clock->nsec; - } +stop: + return 1; +} + +static int setup_matching(struct impl *this) +{ + struct port *port = &this->port; + + if (this->position && port->rate_match) { + port->rate_match->rate = 1 / port->buffer.corr; + + this->matching = this->following; + this->resampling = this->matching || + (port->current_format.info.raw.rate != this->position->clock.rate.denom); + } else { + this->matching = false; + this->resampling = false; } - /* done if there are no buffers ready */ - if (spa_list_is_empty(&port->ready)) - return 0; + if (port->rate_match) + SPA_FLAG_UPDATE(port->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE, this->matching); - if (this->following) - return 0; + return 0; +} - /* process the buffer if IO does not have any */ - if (io->status != SPA_STATUS_HAVE_DATA) { - struct buffer *b; +static void sco_on_timeout(struct spa_source *source) +{ + struct impl *this = source->data; + struct port *port = &this->port; + uint64_t exp, duration; + uint32_t rate; + struct spa_io_buffers *io = port->io; + uint64_t prev_time, now_time; + + if (this->transport == NULL) + return; - if (io->buffer_id < port->n_buffers) - recycle_buffer(this, port, io->buffer_id); + if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0) + spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno)); - b = spa_list_first(&port->ready, struct buffer, link); - spa_list_remove(&b->link); - b->outstanding = true; + prev_time = this->current_time; + now_time = this->current_time = this->next_time; - io->buffer_id = b->id; - io->status = SPA_STATUS_HAVE_DATA; + spa_log_trace(this->log, "%p: timer %"PRIu64" %"PRIu64"", this, + now_time, now_time - prev_time); + + if (SPA_LIKELY(this->position)) { + duration = this->position->clock.duration; + rate = this->position->clock.rate.denom; + } else { + duration = 1024; + rate = 48000; } - /* notify ready */ + setup_matching(this); + + this->next_time = now_time + duration * SPA_NSEC_PER_SEC / port->buffer.corr / rate; + + if (SPA_LIKELY(this->clock)) { + this->clock->nsec = now_time; + this->clock->position += duration; + this->clock->duration = duration; + this->clock->rate_diff = port->buffer.corr; + this->clock->next_nsec = this->next_time; + } + + spa_log_trace(this->log, "%p: %d", this, io->status); + io->status = SPA_STATUS_HAVE_DATA; spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA); - return 0; -stop: - return 1; + set_timeout(this, this->next_time); } static int do_add_source(struct spa_loop *loop, @@ -613,6 +645,7 @@ static int do_start(struct impl *this) { + struct port *port = &this->port; bool do_accept; int res; @@ -636,7 +669,13 @@ return res; /* Reset the buffers and sample count */ - reset_buffers(&this->port); + reset_buffers(port); + + spa_bt_decode_buffer_clear(&port->buffer); + if ((res = spa_bt_decode_buffer_init(&port->buffer, this->log, + port->frame_size, port->current_format.info.raw.rate, + this->quantum_limit, this->quantum_limit)) < 0) + return res; /* Init mSBC if needed */ if (this->transport->codec == HFP_AUDIO_CODEC_MSBC) { @@ -653,6 +692,17 @@ goto fail; spa_loop_invoke(this->data_loop, do_add_source, 0, NULL, 0, true, this); + /* Start timer */ + this->timer_source.data = this; + this->timer_source.fd = this->timerfd; + this->timer_source.func = sco_on_timeout; + this->timer_source.mask = SPA_IO_IN; + this->timer_source.rmask = 0; + spa_loop_add_source(this->data_loop, &this->timer_source); + + setup_matching(this); + set_timers(this); + /* Set the started flag */ this->started = true; @@ -671,15 +721,25 @@ void *user_data) { struct impl *this = user_data; + struct itimerspec ts; if (this->transport && this->transport->sco_io) spa_bt_sco_io_set_source_cb(this->transport->sco_io, NULL, NULL); + if (this->timer_source.loop) + spa_loop_remove_source(this->data_loop, &this->timer_source); + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = 0; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + spa_system_timerfd_settime(this->data_system, this->timerfd, 0, &ts, NULL); + return 0; } static int do_stop(struct impl *this) { + struct port *port = &this->port; int res = 0; if (!this->started) @@ -696,6 +756,8 @@ res = spa_bt_transport_release(this->transport); } + spa_bt_decode_buffer_clear(&port->buffer); + return res; } @@ -738,12 +800,9 @@ { SPA_KEY_MEDIA_CLASS, "Audio/Source" }, { SPA_KEY_NODE_DRIVER, "true" }, }; - - char latency64 = "128/8000"; const struct spa_dict_item ag_node_info_items = { { SPA_KEY_DEVICE_API, "bluez5" }, { SPA_KEY_MEDIA_CLASS, "Stream/Output/Audio" }, - { SPA_KEY_NODE_LATENCY, latency }, { "media.name", ((this->transport && this->transport->device->name) ? this->transport->device->name : "HSP/HFP") }, }; @@ -753,9 +812,6 @@ if (full) this->info.change_mask = this->info_all; if (this->info.change_mask) { - if (this->transport && this->port.have_format) - snprintf(latency, sizeof(latency), "%d/%d", (int)this->props.min_latency, - (int)this->port.current_format.info.raw.rate); this->info.props = is_ag ? &SPA_DICT_INIT_ARRAY(ag_node_info_items) : &SPA_DICT_INIT_ARRAY(hu_node_info_items); @@ -902,11 +958,11 @@ param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_ParamBuffers, id, - SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 8, MAX_BUFFERS), + SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - this->props.max_latency * port->frame_size, - this->props.min_latency * port->frame_size, + this->quantum_limit * port->frame_size, + 16 * port->frame_size, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->frame_size)); break; @@ -976,7 +1032,6 @@ spa_list_init(&port->ready); port->n_buffers = 0; } - port->current_buffer = NULL; return 0; } @@ -1147,6 +1202,79 @@ return 0; } +static uint32_t get_samples(struct impl *this, uint32_t *duration) +{ + struct port *port = &this->port; + uint32_t samples; + + if (SPA_LIKELY(port->rate_match) && this->resampling) { + samples = port->rate_match->size; + } else { + if (SPA_LIKELY(this->position)) + samples = this->position->clock.duration * port->current_format.info.raw.rate + / this->position->clock.rate.denom; + else + samples = 1024; + } + + if (SPA_LIKELY(this->position)) + *duration = this->position->clock.duration * port->current_format.info.raw.rate + / this->position->clock.rate.denom; + else if (SPA_LIKELY(this->clock)) + *duration = this->clock->duration * port->current_format.info.raw.rate + / this->clock->rate.denom; + else + *duration = 1024 * port->current_format.info.raw.rate / 48000; + + return samples; +} + +static void process_buffering(struct impl *this) +{ + struct port *port = &this->port; + uint32_t duration; + const uint32_t samples = get_samples(this, &duration); + void *buf; + uint32_t avail; + + spa_bt_decode_buffer_process(&port->buffer, samples, duration); + + setup_matching(this); + + buf = spa_bt_decode_buffer_get_read(&port->buffer, &avail); + + /* copy data to buffers */ + if (!spa_list_is_empty(&port->free) && avail > 0) { + struct buffer *buffer; + struct spa_data *datas; + uint32_t data_size; + + data_size = samples * port->frame_size; + + avail = SPA_MIN(avail, data_size); + + spa_bt_decode_buffer_read(&port->buffer, avail); + + buffer = spa_list_first(&port->free, struct buffer, link); + spa_list_remove(&buffer->link); + + spa_log_trace(this->log, "dequeue %d", buffer->id); + + datas = buffer->buf->datas; + + spa_assert(datas0.maxsize >= data_size); + + datas0.chunk->offset = 0; + datas0.chunk->size = avail; + datas0.chunk->stride = port->frame_size; + memcpy(datas0.data, buf, avail); + + /* ready buffer if full */ + spa_log_trace(this->log, "queue %d frames:%d", buffer->id, (int)avail / port->frame_size); + spa_list_append(&port->ready, &buffer->link); + } +} + static int impl_node_process(void *object) { struct impl *this = object; @@ -1170,6 +1298,9 @@ io->buffer_id = SPA_ID_INVALID; } + /* Produce data */ + process_buffering(this); + /* Return if there are no buffers ready to be processed */ if (spa_list_is_empty(&port->ready)) return SPA_STATUS_OK; @@ -1252,6 +1383,8 @@ struct impl *this = (struct impl *) handle; if (this->transport) spa_hook_remove(&this->transport_listener); + spa_system_close(this->data_system, this->timerfd); + spa_bt_decode_buffer_clear(&this->port.buffer); return 0; } @@ -1341,6 +1474,10 @@ spa_list_init(&port->ready); spa_list_init(&port->free); + this->quantum_limit = 8192; + if (info && (str = spa_dict_lookup(info, "clock.quantum-limit"))) + spa_atou32(str, &this->quantum_limit, 0); + if (info && (str = spa_dict_lookup(info, SPA_KEY_API_BLUEZ5_TRANSPORT))) sscanf(str, "pointer:%p", &this->transport); @@ -1351,6 +1488,9 @@ spa_bt_transport_add_listener(this->transport, &this->transport_listener, &transport_events, this); + this->timerfd = spa_system_timerfd_create(this->data_system, + CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); + return 0; }
View file
pipewire-0.3.53.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.54.tar.gz/spa/plugins/support/null-audio-sink.c
Changed
@@ -42,6 +42,7 @@ #include <spa/node/keys.h> #include <spa/param/audio/format-utils.h> #include <spa/debug/types.h> +#include <spa/debug/mem.h> #include <spa/param/audio/type-info.h> #include <spa/param/param.h> #include <spa/pod/filter.h> @@ -57,6 +58,7 @@ uint32_t n_pos; uint32_t posSPA_AUDIO_MAX_CHANNELS; char clock_name64; + unsigned int debug:1; }; static void reset_props(struct props *props) @@ -65,6 +67,7 @@ props->rate = 0; props->n_pos = 0; strncpy(props->clock_name, DEFAULT_CLOCK_NAME, sizeof(props->clock_name)); + props->debug = false; } #define DEFAULT_CHANNELS 2 @@ -744,6 +747,20 @@ io->status = -EINVAL; return io->status; } + if (this->props.debug) { + struct buffer *b; + uint32_t i; + + b = &port->buffersio->buffer_id; + for (i = 0; i < b->outbuf->n_datas; i++) { + uint32_t offs, size; + struct spa_data *d = b->outbuf->datas; + + offs = SPA_MIN(d->chunk->offset, d->maxsize); + size = SPA_MIN(d->maxsize - offs, d->chunk->size); + spa_debug_mem(i, SPA_PTROFF(di.data, offs, void), SPA_MIN(16u, size));; + } + } io->status = SPA_STATUS_OK; return SPA_STATUS_HAVE_DATA; }
View file
pipewire-0.3.53.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.54.tar.gz/src/modules/module-protocol-pulse/client.c
Changed
@@ -177,6 +177,9 @@ free(client->default_sink); free(client->default_source); + free(client->temporary_default_sink); + free(client->temporary_default_source); + pw_properties_free(client->props); pw_properties_free(client->routes);
View file
pipewire-0.3.53.tar.gz/src/modules/module-protocol-pulse/client.h -> pipewire-0.3.54.tar.gz/src/modules/module-protocol-pulse/client.h
Changed
@@ -75,6 +75,8 @@ struct pw_manager_object *metadata_default; char *default_sink; char *default_source; + char *temporary_default_sink; /**< pending value, for MOVE_* commands */ + char *temporary_default_source; /**< pending value, for MOVE_* commands */ struct pw_manager_object *metadata_routes; struct pw_properties *routes;
View file
pipewire-0.3.53.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.54.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -678,8 +678,8 @@ latency = attr->fragsize; } /* make sure can queue at least to fragsize without overruns */ - if (attr->maxlength < attr->fragsize * 2) - attr->maxlength = attr->fragsize * 2; + if (attr->maxlength < attr->fragsize * 4) + attr->maxlength = attr->fragsize * 4; pw_log_info("%s maxlength:%u fragsize:%u minfrag:%u latency:%u", s->client->name, attr->maxlength, attr->fragsize, minfrag, @@ -961,6 +961,8 @@ free(client->default_sink); client->default_sink = value ? strdup(value) : NULL; } + free(client->temporary_default_sink); + client->temporary_default_sink = NULL; } if (key == NULL || spa_streq(key, "default.audio.source")) { if (value != NULL) { @@ -974,6 +976,8 @@ free(client->default_source); client->default_source = value ? strdup(value) : NULL; } + free(client->temporary_default_source); + client->temporary_default_source = NULL; } if (changed) send_default_change_subscribe_event(client, true, true); @@ -1801,7 +1805,7 @@ struct channel_map map; uint32_t source_index; const char *source_name; - struct buffer_attr attr; + struct buffer_attr attr = { 0 }; bool corked = false, no_remap = false, no_remix = false, @@ -3685,6 +3689,27 @@ return 0; } +static int fill_sink_info_proplist(struct message *m, const struct spa_dict *sink_props, + const struct pw_manager_object *card) +{ + struct pw_device_info *card_info = card ? card->info : NULL; + struct pw_properties *props = NULL; + + if (card_info && card_info->props) { + props = pw_properties_new_dict(sink_props); + if (props == NULL) + return -ENOMEM; + + pw_properties_add(props, card_info->props); + sink_props = &props->dict; + } + message_put(m, TAG_PROPLIST, sink_props, TAG_INVALID); + + pw_properties_free(props); + + return 0; +} + static int fill_sink_info(struct client *client, struct message *m, struct pw_manager_object *o) { @@ -3777,8 +3802,10 @@ TAG_INVALID); if (client->version >= 13) { + int res; + if ((res = fill_sink_info_proplist(m, info->props, card)) < 0) + return res; message_put(m, - TAG_PROPLIST, info->props, TAG_USEC, 0LL, /* requested latency */ TAG_INVALID); } @@ -3867,22 +3894,27 @@ return 0; } -static int fill_source_info_proplist(struct message *m, struct pw_manager_object *o, - struct pw_node_info *info) +static int fill_source_info_proplist(struct message *m, const struct spa_dict *source_props, + const struct pw_manager_object *card, const bool is_monitor) { + struct pw_device_info *card_info = card ? card->info : NULL; struct pw_properties *props = NULL; - struct spa_dict *props_dict = info->props; - if (pw_manager_object_is_monitor(o)) { - props = pw_properties_new_dict(info->props); + if ((card_info && card_info->props) || is_monitor) { + props = pw_properties_new_dict(source_props); if (props == NULL) return -ENOMEM; - pw_properties_set(props, PW_KEY_DEVICE_CLASS, "monitor"); - props_dict = &props->dict; + if (card_info && card_info->props) + pw_properties_add(props, card_info->props); + + if (is_monitor) + pw_properties_set(props, PW_KEY_DEVICE_CLASS, "monitor"); + + source_props = &props->dict; } + message_put(m, TAG_PROPLIST, source_props, TAG_INVALID); - message_put(m, TAG_PROPLIST, props_dict, TAG_INVALID); pw_properties_free(props); return 0; @@ -3984,7 +4016,7 @@ if (client->version >= 13) { int res; - if ((res = fill_source_info_proplist(m, o, info)) < 0) + if ((res = fill_source_info_proplist(m, info->props, card, is_monitor)) < 0) return res; message_put(m, TAG_USEC, 0LL, /* requested latency */ @@ -4723,6 +4755,20 @@ if (res < 0) return res; + /* + * The metadata is not necessarily updated within one server sync. + * Correct functioning of MOVE_* commands requires knowing the current + * default target, so we need to stash temporary values here in case + * the client emits them before metadata gets updated. + */ + if (sink) { + free(client->temporary_default_sink); + client->temporary_default_sink = name ? strdup(name) : NULL; + } else { + free(client->temporary_default_source); + client->temporary_default_source = name ? strdup(name) : NULL; + } + return operation_new(client, tag); } @@ -4764,6 +4810,7 @@ int target_id; int64_t target_serial; const char *name_device; + const char *name; struct pw_node_info *info; struct selector sel; int res; @@ -4800,7 +4847,13 @@ if ((dev = find_device(client, index_device, name_device, sink, NULL)) == NULL) return -ENOENT; - dev_default = find_device(client, SPA_ID_INVALID, NULL, sink, NULL); + /* + * The client metadata is not necessarily yet updated after SET_DEFAULT command, + * so use the temporary values if they are still set. + */ + name = sink ? client->temporary_default_sink : client->temporary_default_source; + dev_default = find_device(client, SPA_ID_INVALID, name, sink, NULL); + if (dev == dev_default) { /* * When moving streams to a node that is equal to the default, @@ -4826,6 +4879,11 @@ SPA_TYPE_INFO_BASE"Id", "%"PRIi64, target_serial)) < 0) return res; + name = spa_dict_lookup(info->props, PW_KEY_NODE_NAME); + pw_log_debug("%s %s done tag:%u index:%u name:%s target:%d target-serial:%"PRIi64, client->name, + commandscommand.name, tag, index, name ? name : "<null>", + target_id, target_serial); + /* We will temporarily claim the stream was already moved */ set_temporary_move_target(client, o, dev->index); send_object_event(client, o, SUBSCRIPTION_EVENT_CHANGE);
View file
pipewire-0.3.53.tar.gz/src/tools/dsffile.c -> pipewire-0.3.54.tar.gz/src/tools/dsffile.c
Changed
@@ -216,13 +216,15 @@ uint8_t *d = data; int step = SPA_ABS(layout->interleave); bool rev = layout->lsb != f->info.lsb; - size_t total, block, offset, pos; + size_t total, block, offset, pos, scale; block = f->offset / f->info.blocksize; offset = block * f->info.blocksize * f->info.channels; pos = f->offset % f->info.blocksize; + scale = SPA_CLAMP(f->info.rate / (44100u * 64u), 1u, 4u); samples *= step; + samples *= scale; for (total = 0; total < samples && offset + pos < f->info.length; total++) { const uint8_t *s = f->p + offset + pos;
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.