mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	filter-chain: add more convolver options
Add gain, delay, offset, length, channels options. Make default blocksize depend on the ir length.
This commit is contained in:
		
							parent
							
								
									dbe9f02471
								
							
						
					
					
						commit
						755eab0cd3
					
				
					 3 changed files with 140 additions and 20 deletions
				
			
		| 
						 | 
				
			
			@ -34,19 +34,108 @@ context.modules = [
 | 
			
		|||
                nodes = [
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        name = convolver
 | 
			
		||||
                        label = convolver
 | 
			
		||||
                        name = convFL
 | 
			
		||||
			config = {
 | 
			
		||||
			   filename = "src/modules/module-filter-chain/street2-L.wav"
 | 
			
		||||
			   blocksize = 512
 | 
			
		||||
			   filename = "hrir_kemar/hrir-kemar.wav"
 | 
			
		||||
			   channel = 0
 | 
			
		||||
			}
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = convolver
 | 
			
		||||
                        name = convFR
 | 
			
		||||
			config = {
 | 
			
		||||
			   filename = "hrir_kemar/hrir-kemar.wav"
 | 
			
		||||
			   channel = 4
 | 
			
		||||
			}
 | 
			
		||||
		    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = convolver
 | 
			
		||||
                        name = convFC
 | 
			
		||||
			config = {
 | 
			
		||||
			   filename = "hrir_kemar/hrir-kemar.wav"
 | 
			
		||||
			   channel = 2
 | 
			
		||||
			}
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = convolver
 | 
			
		||||
                        name = convLFE
 | 
			
		||||
			config = {
 | 
			
		||||
			   filename = "hrir_kemar/hrir-kemar.wav"
 | 
			
		||||
			   channel = 3
 | 
			
		||||
			}
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = convolver
 | 
			
		||||
                        name = convSL
 | 
			
		||||
			config = {
 | 
			
		||||
			   filename = "hrir_kemar/hrir-kemar.wav"
 | 
			
		||||
			   channel = 1
 | 
			
		||||
			}
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = convolver
 | 
			
		||||
                        name = convSR
 | 
			
		||||
			config = {
 | 
			
		||||
			   filename = "hrir_kemar/hrir-kemar.wav"
 | 
			
		||||
			   channel = 5
 | 
			
		||||
			}
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = mixer
 | 
			
		||||
                        name = mix1L
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = mixer
 | 
			
		||||
                        name = mix1R
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = mixer
 | 
			
		||||
                        name = mixC
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = mixer
 | 
			
		||||
                        name = mix2L
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        type = builtin
 | 
			
		||||
                        label = mixer
 | 
			
		||||
                        name = mix2R
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
		links = [
 | 
			
		||||
                    { output = "convFL:Out" input = "mix1L:In 1" }
 | 
			
		||||
                    { output = "convSL:Out" input = "mix1L:In 2" }
 | 
			
		||||
 | 
			
		||||
                    { output = "convFR:Out" input = "mix1R:In 1" }
 | 
			
		||||
                    { output = "convSR:Out" input = "mix1R:In 2" }
 | 
			
		||||
 | 
			
		||||
                    { output = "convFC:Out" input = "mixC:In 1" }
 | 
			
		||||
                    { output = "convLFE:Out" input = "mixC:In 2" }
 | 
			
		||||
 | 
			
		||||
                    { output = "mixC:Out" input = "mix2L:In 1" }
 | 
			
		||||
                    { output = "mix1L:Out" input = "mix2L:In 2" }
 | 
			
		||||
 | 
			
		||||
                    { output = "mixC:Out" input = "mix2R:In 1" }
 | 
			
		||||
                    { output = "mix1R:Out" input = "mix2R:In 2" }
 | 
			
		||||
                ]
 | 
			
		||||
                inputs = [ "convFL:In" "convFR:In" "convFC:In" "convLFE:In" "convSL:In" "convSR:In" ]
 | 
			
		||||
                outputs = [ "mix2L:Out" "mix2R:Out" ]
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            capture.props = {
 | 
			
		||||
                media.class = Audio/Sink
 | 
			
		||||
                audio.channels = 2
 | 
			
		||||
                audio.position = [ FL FR ]
 | 
			
		||||
                audio.channels = 6
 | 
			
		||||
                audio.position = [ FL FR FC LFE SL SR]
 | 
			
		||||
            }
 | 
			
		||||
            playback.props = {
 | 
			
		||||
                node.passive = true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -393,12 +393,14 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
 | 
			
		|||
	SF_INFO info;
 | 
			
		||||
	SNDFILE *f;
 | 
			
		||||
	float *samples;
 | 
			
		||||
	int i, offset;
 | 
			
		||||
	int i, offset = 0, length = 0, channel = index, n_frames;
 | 
			
		||||
	struct spa_json it[2];
 | 
			
		||||
	const char *val;
 | 
			
		||||
	char key[256];
 | 
			
		||||
	char filename[PATH_MAX] = "";
 | 
			
		||||
	int blocksize = 256;
 | 
			
		||||
	int blocksize = 0;
 | 
			
		||||
	int delay = 0;
 | 
			
		||||
	float gain = 1.0f;
 | 
			
		||||
 | 
			
		||||
	if (config == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -408,16 +410,32 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
 | 
			
		|||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
 | 
			
		||||
		if (spa_streq(key, "filename")) {
 | 
			
		||||
			if (spa_json_get_string(&it[1], filename, sizeof(filename)) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_streq(key, "blocksize")) {
 | 
			
		||||
		if (spa_streq(key, "blocksize")) {
 | 
			
		||||
			if (spa_json_get_int(&it[1], &blocksize) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_streq(key, "gain")) {
 | 
			
		||||
			if (spa_json_get_float(&it[1], &gain) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_streq(key, "delay")) {
 | 
			
		||||
			if (spa_json_get_int(&it[1], &delay) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_streq(key, "filename")) {
 | 
			
		||||
			if (spa_json_get_string(&it[1], filename, sizeof(filename)) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_streq(key, "offset")) {
 | 
			
		||||
			if (spa_json_get_int(&it[1], &index) <= 0)
 | 
			
		||||
			if (spa_json_get_int(&it[1], &offset) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_streq(key, "length")) {
 | 
			
		||||
			if (spa_json_get_int(&it[1], &length) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_streq(key, "channel")) {
 | 
			
		||||
			if (spa_json_get_int(&it[1], &channel) <= 0)
 | 
			
		||||
				return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		else if (spa_json_next(&it[1], &val) < 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -439,18 +457,31 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
 | 
			
		|||
 | 
			
		||||
	impl->rate = SampleRate;
 | 
			
		||||
 | 
			
		||||
	samples = malloc(info.frames * sizeof(float) * info.channels);
 | 
			
		||||
	if (length == 0)
 | 
			
		||||
		length = info.frames;
 | 
			
		||||
	else
 | 
			
		||||
		length = SPA_MIN(length, info.frames);
 | 
			
		||||
 | 
			
		||||
	length -= SPA_MIN(offset, length);
 | 
			
		||||
 | 
			
		||||
	n_frames = delay + length;
 | 
			
		||||
 | 
			
		||||
	if (blocksize == 0)
 | 
			
		||||
		blocksize = SPA_CLAMP(n_frames, 64, 256);
 | 
			
		||||
 | 
			
		||||
	samples = calloc(sizeof(float), n_frames * info.channels);
 | 
			
		||||
        if (samples == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	sf_readf_float(f, samples, info.frames);
 | 
			
		||||
	sf_seek(f, offset, SEEK_SET);
 | 
			
		||||
	sf_readf_float(f, samples + (delay * info.channels), length);
 | 
			
		||||
 | 
			
		||||
	offset = index % info.channels;
 | 
			
		||||
	channel = channel % info.channels;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < info.frames; i++)
 | 
			
		||||
		samples[i] = samples[info.channels * i + offset];
 | 
			
		||||
	for (i = 0; i < n_frames; i++)
 | 
			
		||||
		samples[i] = samples[info.channels * i + channel] * gain;
 | 
			
		||||
 | 
			
		||||
	impl->conv = convolver_new(blocksize, samples, info.frames);
 | 
			
		||||
	impl->conv = convolver_new(blocksize, samples, n_frames);
 | 
			
		||||
 | 
			
		||||
	free(samples);
 | 
			
		||||
	sf_close(f);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,7 +180,7 @@ int convolver_run(struct convolver *conv, const float *input, float *output, int
 | 
			
		|||
		kiss_fftri_f32(conv->ifft, conv->conv, conv->fft_buffer);
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < conv->segSize; i++)
 | 
			
		||||
			conv->fft_buffer[i] /= conv->segSize * 2;
 | 
			
		||||
			conv->fft_buffer[i] /= conv->segSize;
 | 
			
		||||
 | 
			
		||||
		Sum(output + processed, conv->fft_buffer + inputBufferPos, conv->overlap + inputBufferPos, processing);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue