• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2018 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <syslog.h>
7 
8 #include "buffer_share.h"
9 #include "cras_audio_area.h"
10 #include "cras_dsp_pipeline.h"
11 #include "cras_mix.h"
12 #include "cras_rstream.h"
13 #include "cras_system_state.h"
14 #include "dsp_util.h"
15 #include "input_data.h"
16 #include "utlist.h"
17 
input_data_run(struct ext_dsp_module * ext,unsigned int nframes)18 void input_data_run(struct ext_dsp_module *ext,
19 		    unsigned int nframes)
20 {
21 	struct input_data *data = (struct input_data *)ext;
22 	float *const *wp;
23 	int i;
24 	unsigned int writable;
25 	unsigned int offset = 0;
26 
27 	while (nframes) {
28 		writable = float_buffer_writable(data->fbuffer);
29 		writable = MIN(nframes, writable);
30 		if (!writable) {
31 			syslog(LOG_ERR, "Not enough space to process input data");
32 			break;
33 		}
34 		wp = float_buffer_write_pointer(data->fbuffer);
35 		for (i = 0; i < data->fbuffer->num_channels; i++)
36 			memcpy(wp[i], ext->ports[i] + offset, writable * sizeof(float));
37 
38 		float_buffer_written(data->fbuffer, writable);
39 		nframes -= writable;
40 		offset += writable;
41 	}
42 }
43 
input_data_configure(struct ext_dsp_module * ext,unsigned int buffer_size,unsigned int num_channels,unsigned int rate)44 void input_data_configure(struct ext_dsp_module *ext, unsigned int buffer_size,
45 			  unsigned int num_channels, unsigned int rate)
46 {
47 	struct input_data *data = (struct input_data *)ext;
48 
49 	if (data->fbuffer)
50 		float_buffer_destroy(&data->fbuffer);
51 	data->fbuffer = float_buffer_create(buffer_size, num_channels);
52 }
53 
input_data_create(void * dev_ptr)54 struct input_data *input_data_create(void *dev_ptr)
55 {
56 	struct input_data *data = (struct input_data *)calloc(1, sizeof(*data));
57 
58 	data->dev_ptr = dev_ptr;
59 
60 	data->ext.run = input_data_run;
61 	data->ext.configure = input_data_configure;
62 
63 	return data;
64 }
65 
input_data_destroy(struct input_data ** data)66 void input_data_destroy(struct input_data **data)
67 {
68 	if ((*data)->fbuffer)
69 		float_buffer_destroy(&(*data)->fbuffer);
70 	free(*data);
71 	*data = NULL;
72 }
73 
input_data_set_all_streams_read(struct input_data * data,unsigned int nframes)74 void input_data_set_all_streams_read(struct input_data *data,
75 				     unsigned int nframes)
76 {
77 	if (!data->fbuffer)
78 		return;
79 
80 	if (float_buffer_level(data->fbuffer) < nframes) {
81 		syslog(LOG_ERR, "All streams read %u frames exceeds %u"
82 		       " in input_data's buffer",
83 		       nframes, float_buffer_level(data->fbuffer));
84 		float_buffer_reset(data->fbuffer);
85 		return;
86 	}
87 	float_buffer_read(data->fbuffer, nframes);
88 }
89 
input_data_get_for_stream(struct input_data * data,struct cras_rstream * stream,struct buffer_share * offsets,struct cras_audio_area ** area,unsigned int * offset)90 int input_data_get_for_stream(struct input_data *data,
91 			      struct cras_rstream *stream,
92 			      struct buffer_share *offsets,
93 			      struct cras_audio_area **area,
94 			      unsigned int *offset)
95 {
96 	unsigned int apm_processed;
97 	struct cras_apm *apm;
98 
99 	/*
100 	 * It is possible that area buffer frames is smaller than the
101 	 * offset of stream. In this case, just reset the offset value
102 	 * to area->frames to prevent caller using these information get
103 	 * bad access to data.
104 	 */
105 	*area = data->area;
106 	*offset = MIN(buffer_share_id_offset(offsets, stream->stream_id),
107 		      data->area->frames);
108 
109 	apm = cras_apm_list_get(stream->apm_list, data->dev_ptr);
110 	if (apm == NULL)
111 		return 0;
112 
113 	apm_processed = cras_apm_list_process(apm, data->fbuffer, *offset);
114 	if (apm_processed < 0) {
115 		cras_apm_list_remove(stream->apm_list, apm);
116 		return 0;
117 	}
118 	buffer_share_offset_update(offsets, stream->stream_id, apm_processed);
119 	*area = cras_apm_list_get_processed(apm);
120 	*offset = 0;
121 
122 	return 0;
123 }
124 
input_data_put_for_stream(struct input_data * data,struct cras_rstream * stream,struct buffer_share * offsets,unsigned int frames)125 int input_data_put_for_stream(struct input_data *data,
126 			      struct cras_rstream *stream,
127 			      struct buffer_share *offsets,
128 			      unsigned int frames)
129 {
130 	struct cras_apm *apm = cras_apm_list_get(
131 			stream->apm_list, data->dev_ptr);
132 
133 	if (apm)
134 		cras_apm_list_put_processed(apm, frames);
135 	else
136 		buffer_share_offset_update(offsets, stream->stream_id, frames);
137 
138 	return 0;
139 }
140