mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	Fix the downsampling noise problem
Description: The patch replaces the nearest neighbor downsampling method in the sample rate conversion plugin by linear interpolation of the closest two samples, thus significantly reducing the resampling noise. Signed-off-by: Markus Grabner <grabner@icg.tu-graz.ac.at>
This commit is contained in:
		
							parent
							
								
									cc17f92972
								
							
						
					
					
						commit
						3a8bfd43d7
					
				
					 1 changed files with 11 additions and 2 deletions
				
			
		| 
						 | 
					@ -45,7 +45,8 @@ const char *_snd_module_pcm_rate = "";
 | 
				
			||||||
#ifndef DOC_HIDDEN
 | 
					#ifndef DOC_HIDDEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* LINEAR_DIV needs to be large enough to handle resampling from 192000 -> 8000 */
 | 
					/* LINEAR_DIV needs to be large enough to handle resampling from 192000 -> 8000 */
 | 
				
			||||||
#define LINEAR_DIV (1<<19)
 | 
					#define LINEAR_DIV_SHIFT 19
 | 
				
			||||||
 | 
					#define LINEAR_DIV (1<<LINEAR_DIV_SHIFT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum rate_type {
 | 
					enum rate_type {
 | 
				
			||||||
	RATE_TYPE_LINEAR,		/* linear interpolation */
 | 
						RATE_TYPE_LINEAR,		/* linear interpolation */
 | 
				
			||||||
| 
						 | 
					@ -206,9 +207,12 @@ static void snd_pcm_rate_shrink(const snd_pcm_channel_area_t *dst_areas,
 | 
				
			||||||
		const char *src;
 | 
							const char *src;
 | 
				
			||||||
		char *dst;
 | 
							char *dst;
 | 
				
			||||||
		int src_step, dst_step;
 | 
							int src_step, dst_step;
 | 
				
			||||||
 | 
							int16_t old_sample = 0;
 | 
				
			||||||
 | 
							int16_t new_sample = 0;
 | 
				
			||||||
 | 
							int old_weight, new_weight;
 | 
				
			||||||
		sum = states->u.linear.sum;
 | 
							sum = states->u.linear.sum;
 | 
				
			||||||
		//int16_t old_sample = states->u.linear.old_sample;
 | 
							//int16_t old_sample = states->u.linear.old_sample;
 | 
				
			||||||
		pos = LINEAR_DIV/2; /* Start at 0.5 */
 | 
							pos = LINEAR_DIV - get_increment; /* Force first sample to be copied */
 | 
				
			||||||
		states->u.linear.init = 0;
 | 
							states->u.linear.init = 0;
 | 
				
			||||||
		src = snd_pcm_channel_area_addr(src_area, src_offset);
 | 
							src = snd_pcm_channel_area_addr(src_area, src_offset);
 | 
				
			||||||
		dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
 | 
							dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
 | 
				
			||||||
| 
						 | 
					@ -223,11 +227,15 @@ static void snd_pcm_rate_shrink(const snd_pcm_channel_area_t *dst_areas,
 | 
				
			||||||
#include "plugin_ops.h"
 | 
					#include "plugin_ops.h"
 | 
				
			||||||
#undef GET16_END
 | 
					#undef GET16_END
 | 
				
			||||||
		after_get:
 | 
							after_get:
 | 
				
			||||||
 | 
								new_sample = sample;
 | 
				
			||||||
			src += src_step;
 | 
								src += src_step;
 | 
				
			||||||
			src_frames1++;
 | 
								src_frames1++;
 | 
				
			||||||
			pos += get_increment;
 | 
								pos += get_increment;
 | 
				
			||||||
			if (pos >= LINEAR_DIV) {
 | 
								if (pos >= LINEAR_DIV) {
 | 
				
			||||||
				pos -= LINEAR_DIV;
 | 
									pos -= LINEAR_DIV;
 | 
				
			||||||
 | 
									old_weight = (pos << (32 - LINEAR_DIV_SHIFT)) / (get_increment >> (LINEAR_DIV_SHIFT - 16));
 | 
				
			||||||
 | 
									new_weight = 0x10000 - old_weight;
 | 
				
			||||||
 | 
									sample = (old_sample * old_weight + new_sample * new_weight) >> 16;
 | 
				
			||||||
				goto *put;
 | 
									goto *put;
 | 
				
			||||||
#define PUT16_END after_put
 | 
					#define PUT16_END after_put
 | 
				
			||||||
#include "plugin_ops.h"
 | 
					#include "plugin_ops.h"
 | 
				
			||||||
| 
						 | 
					@ -237,6 +245,7 @@ static void snd_pcm_rate_shrink(const snd_pcm_channel_area_t *dst_areas,
 | 
				
			||||||
				dst_frames1++;
 | 
									dst_frames1++;
 | 
				
			||||||
				assert(dst_frames1 <= dst_frames);
 | 
									assert(dst_frames1 <= dst_frames);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								old_sample = new_sample;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		states->u.linear.sum = sum;
 | 
							states->u.linear.sum = sum;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue