pcm_utils: moved code to pcm_volume.c
Moved the software volume code to a separate library.
This commit is contained in:
		| @@ -50,6 +50,7 @@ mpd_headers = \ | |||||||
| 	path.h \ | 	path.h \ | ||||||
| 	mapper.h \ | 	mapper.h \ | ||||||
| 	pcm_utils.h \ | 	pcm_utils.h \ | ||||||
|  | 	pcm_volume.h \ | ||||||
| 	pcm_channels.h \ | 	pcm_channels.h \ | ||||||
| 	pcm_resample.h \ | 	pcm_resample.h \ | ||||||
| 	pcm_dither.h \ | 	pcm_dither.h \ | ||||||
| @@ -129,6 +130,7 @@ mpd_SOURCES = \ | |||||||
| 	path.c \ | 	path.c \ | ||||||
| 	mapper.c \ | 	mapper.c \ | ||||||
| 	pcm_utils.c \ | 	pcm_utils.c \ | ||||||
|  | 	pcm_volume.c \ | ||||||
| 	pcm_channels.c \ | 	pcm_channels.c \ | ||||||
| 	pcm_resample.c \ | 	pcm_resample.c \ | ||||||
| 	pcm_dither.c \ | 	pcm_dither.c \ | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ | |||||||
| #include "pcm_utils.h" | #include "pcm_utils.h" | ||||||
| #include "pcm_channels.h" | #include "pcm_channels.h" | ||||||
| #include "pcm_prng.h" | #include "pcm_prng.h" | ||||||
|  | #include "pcm_volume.h" | ||||||
| #include "conf.h" | #include "conf.h" | ||||||
| #include "audio_format.h" | #include "audio_format.h" | ||||||
|  |  | ||||||
| @@ -30,92 +31,6 @@ | |||||||
| #undef G_LOG_DOMAIN | #undef G_LOG_DOMAIN | ||||||
| #define G_LOG_DOMAIN "pcm" | #define G_LOG_DOMAIN "pcm" | ||||||
|  |  | ||||||
| static inline int |  | ||||||
| pcm_dither(void) |  | ||||||
| { |  | ||||||
| 	static unsigned long state; |  | ||||||
| 	uint32_t r; |  | ||||||
|  |  | ||||||
| 	r = state = prng(state); |  | ||||||
|  |  | ||||||
| 	return (r & 511) - ((r >> 9) & 511); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| pcm_volume_change_8(int8_t *buffer, unsigned num_samples, int volume) |  | ||||||
| { |  | ||||||
| 	while (num_samples > 0) { |  | ||||||
| 		int32_t sample = *buffer; |  | ||||||
|  |  | ||||||
| 		sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) |  | ||||||
| 			/ PCM_VOLUME_1; |  | ||||||
|  |  | ||||||
| 		*buffer++ = pcm_range(sample, 8); |  | ||||||
| 		--num_samples; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| pcm_volume_change_16(int16_t *buffer, unsigned num_samples, int volume) |  | ||||||
| { |  | ||||||
| 	while (num_samples > 0) { |  | ||||||
| 		int32_t sample = *buffer; |  | ||||||
|  |  | ||||||
| 		sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) |  | ||||||
| 			/ PCM_VOLUME_1; |  | ||||||
|  |  | ||||||
| 		*buffer++ = pcm_range(sample, 16); |  | ||||||
| 		--num_samples; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume) |  | ||||||
| { |  | ||||||
| 	while (num_samples > 0) { |  | ||||||
| 		int64_t sample = *buffer; |  | ||||||
|  |  | ||||||
| 		sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) |  | ||||||
| 			/ PCM_VOLUME_1; |  | ||||||
|  |  | ||||||
| 		*buffer++ = pcm_range(sample, 24); |  | ||||||
| 		--num_samples; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void pcm_volume(char *buffer, int bufferSize, |  | ||||||
| 		const struct audio_format *format, |  | ||||||
| 		int volume) |  | ||||||
| { |  | ||||||
| 	if (volume == PCM_VOLUME_1) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	if (volume <= 0) { |  | ||||||
| 		memset(buffer, 0, bufferSize); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	switch (format->bits) { |  | ||||||
| 	case 8: |  | ||||||
| 		pcm_volume_change_8((int8_t *)buffer, bufferSize, volume); |  | ||||||
| 		break; |  | ||||||
|  |  | ||||||
| 	case 16: |  | ||||||
| 		pcm_volume_change_16((int16_t *)buffer, bufferSize / 2, |  | ||||||
| 				     volume); |  | ||||||
| 		break; |  | ||||||
|  |  | ||||||
| 	case 24: |  | ||||||
| 		pcm_volume_change_24((int32_t*)buffer, bufferSize / 4, |  | ||||||
| 				     volume); |  | ||||||
| 		break; |  | ||||||
|  |  | ||||||
| 	default: |  | ||||||
| 		g_error("%u bits not supported by pcm_volume!\n", |  | ||||||
| 			format->bits); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void | static void | ||||||
| pcm_add_8(int8_t *buffer1, const int8_t *buffer2, | pcm_add_8(int8_t *buffer1, const int8_t *buffer2, | ||||||
| 	  unsigned num_samples, int volume1, int volume2) | 	  unsigned num_samples, int volume1, int volume2) | ||||||
|   | |||||||
| @@ -29,11 +29,6 @@ | |||||||
|  |  | ||||||
| struct audio_format; | struct audio_format; | ||||||
|  |  | ||||||
| enum { |  | ||||||
| 	/** this value means "100% volume" */ |  | ||||||
| 	PCM_VOLUME_1 = 1000, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct pcm_convert_state { | struct pcm_convert_state { | ||||||
| 	struct pcm_resample_state resample; | 	struct pcm_resample_state resample; | ||||||
|  |  | ||||||
| @@ -57,20 +52,6 @@ pcm_range(int32_t sample, unsigned bits) | |||||||
| 	return sample; | 	return sample; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Converts a float value (0.0 = silence, 1.0 = 100% volume) to an |  | ||||||
|  * integer volume value (1000 = 100%). |  | ||||||
|  */ |  | ||||||
| static inline int |  | ||||||
| pcm_float_to_volume(float volume) |  | ||||||
| { |  | ||||||
| 	return volume * PCM_VOLUME_1 + 0.5; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void pcm_volume(char *buffer, int bufferSize, |  | ||||||
| 		const struct audio_format *format, |  | ||||||
| 		int volume); |  | ||||||
|  |  | ||||||
| void pcm_mix(char *buffer1, const char *buffer2, size_t size, | void pcm_mix(char *buffer1, const char *buffer2, size_t size, | ||||||
|              const struct audio_format *format, float portion1); |              const struct audio_format *format, float portion1); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								src/pcm_volume.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/pcm_volume.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2003-2009 The Music Player Daemon Project | ||||||
|  |  * http://www.musicpd.org | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "pcm_volume.h" | ||||||
|  | #include "pcm_utils.h" | ||||||
|  | #include "audio_format.h" | ||||||
|  |  | ||||||
|  | #include <glib.h> | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #undef G_LOG_DOMAIN | ||||||
|  | #define G_LOG_DOMAIN "pcm_volume" | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | pcm_volume_change_8(int8_t *buffer, unsigned num_samples, int volume) | ||||||
|  | { | ||||||
|  | 	while (num_samples > 0) { | ||||||
|  | 		int32_t sample = *buffer; | ||||||
|  |  | ||||||
|  | 		sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) | ||||||
|  | 			/ PCM_VOLUME_1; | ||||||
|  |  | ||||||
|  | 		*buffer++ = pcm_range(sample, 8); | ||||||
|  | 		--num_samples; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | pcm_volume_change_16(int16_t *buffer, unsigned num_samples, int volume) | ||||||
|  | { | ||||||
|  | 	while (num_samples > 0) { | ||||||
|  | 		int32_t sample = *buffer; | ||||||
|  |  | ||||||
|  | 		sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) | ||||||
|  | 			/ PCM_VOLUME_1; | ||||||
|  |  | ||||||
|  | 		*buffer++ = pcm_range(sample, 16); | ||||||
|  | 		--num_samples; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume) | ||||||
|  | { | ||||||
|  | 	while (num_samples > 0) { | ||||||
|  | 		int64_t sample = *buffer; | ||||||
|  |  | ||||||
|  | 		sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) | ||||||
|  | 			/ PCM_VOLUME_1; | ||||||
|  |  | ||||||
|  | 		*buffer++ = pcm_range(sample, 24); | ||||||
|  | 		--num_samples; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | pcm_volume(char *buffer, int bufferSize, | ||||||
|  | 	   const struct audio_format *format, | ||||||
|  | 	   int volume) | ||||||
|  | { | ||||||
|  | 	if (volume == PCM_VOLUME_1) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	if (volume <= 0) { | ||||||
|  | 		memset(buffer, 0, bufferSize); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	switch (format->bits) { | ||||||
|  | 	case 8: | ||||||
|  | 		pcm_volume_change_8((int8_t *)buffer, bufferSize, volume); | ||||||
|  | 		break; | ||||||
|  |  | ||||||
|  | 	case 16: | ||||||
|  | 		pcm_volume_change_16((int16_t *)buffer, bufferSize / 2, | ||||||
|  | 				     volume); | ||||||
|  | 		break; | ||||||
|  |  | ||||||
|  | 	case 24: | ||||||
|  | 		pcm_volume_change_24((int32_t*)buffer, bufferSize / 4, | ||||||
|  | 				     volume); | ||||||
|  | 		break; | ||||||
|  |  | ||||||
|  | 	default: | ||||||
|  | 		g_error("%u bits not supported by pcm_volume!\n", | ||||||
|  | 			format->bits); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								src/pcm_volume.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/pcm_volume.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2003-2009 The Music Player Daemon Project | ||||||
|  |  * http://www.musicpd.org | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef PCM_VOLUME_H | ||||||
|  | #define PCM_VOLUME_H | ||||||
|  |  | ||||||
|  | #include "pcm_prng.h" | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | enum { | ||||||
|  | 	/** this value means "100% volume" */ | ||||||
|  | 	PCM_VOLUME_1 = 1000, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct audio_format; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Converts a float value (0.0 = silence, 1.0 = 100% volume) to an | ||||||
|  |  * integer volume value (1000 = 100%). | ||||||
|  |  */ | ||||||
|  | static inline int | ||||||
|  | pcm_float_to_volume(float volume) | ||||||
|  | { | ||||||
|  | 	return volume * PCM_VOLUME_1 + 0.5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int | ||||||
|  | pcm_dither(void) | ||||||
|  | { | ||||||
|  | 	static unsigned long state; | ||||||
|  | 	uint32_t r; | ||||||
|  |  | ||||||
|  | 	r = state = prng(state); | ||||||
|  |  | ||||||
|  | 	return (r & 511) - ((r >> 9) & 511); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | pcm_volume(char *buffer, int bufferSize, | ||||||
|  | 	   const struct audio_format *format, | ||||||
|  | 	   int volume); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -22,7 +22,7 @@ | |||||||
| #include "tag.h" | #include "tag.h" | ||||||
| #include "song.h" | #include "song.h" | ||||||
| #include "idle.h" | #include "idle.h" | ||||||
| #include "pcm_utils.h" | #include "pcm_volume.h" | ||||||
| #include "main.h" | #include "main.h" | ||||||
|  |  | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
| #include "player_control.h" | #include "player_control.h" | ||||||
| #include "decoder_control.h" | #include "decoder_control.h" | ||||||
| #include "audio.h" | #include "audio.h" | ||||||
| #include "pcm_utils.h" | #include "pcm_volume.h" | ||||||
| #include "path.h" | #include "path.h" | ||||||
| #include "event_pipe.h" | #include "event_pipe.h" | ||||||
| #include "crossfade.h" | #include "crossfade.h" | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
| #include "replay_gain.h" | #include "replay_gain.h" | ||||||
| #include "conf.h" | #include "conf.h" | ||||||
| #include "audio_format.h" | #include "audio_format.h" | ||||||
| #include "pcm_utils.h" | #include "pcm_volume.h" | ||||||
|  |  | ||||||
| #include <glib.h> | #include <glib.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
| #include "conf.h" | #include "conf.h" | ||||||
| #include "player_control.h" | #include "player_control.h" | ||||||
| #include "idle.h" | #include "idle.h" | ||||||
| #include "pcm_utils.h" | #include "pcm_volume.h" | ||||||
| #include "config.h" | #include "config.h" | ||||||
| #include "audio.h" | #include "audio.h" | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann