mirror of https://github.com/thesofproject/sof.git
Tools: Tune: Improve EQ blob decode scripts
This patch adds user friendly function eq_blob_plot(file) to plot the IIR or FIR equalizer response that will be applied for each channel. The IIR and FIR decoders are modified to better support the higher level script. The copyright texts in impacted scripts are are updated to short BSD-3-Clause style. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
This commit is contained in:
parent
365ffbd02f
commit
594e031b6e
|
@ -0,0 +1,140 @@
|
|||
function eq = eq_blob_plot(blobfn, eqtype, fs, f, doplot)
|
||||
|
||||
% eq = eq_blob_plot(blobfn, eqtype, fs, f, doplot)
|
||||
%
|
||||
% Plot frequency response of IIR or FIR EQ coefficients blob
|
||||
%
|
||||
% Inputs
|
||||
%
|
||||
% blobfn - filename of the blob
|
||||
% eqtype - 'iir' or 'fir', if omitted done via string search from blobfn
|
||||
% fs - sample rate, defaults to 48 kHz if omitted
|
||||
% f - frequency vector
|
||||
% dpplot
|
||||
|
||||
% SPDX-License-Identifier: BSD-3-Clause
|
||||
%
|
||||
% Copyright (c) 2016-2020, Intel Corporation. All rights reserved.
|
||||
%
|
||||
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
|
||||
|
||||
%% Handle input parameters
|
||||
if nargin < 2
|
||||
if findstr(blobfn, '_fir_')
|
||||
eqtype = 'FIR';
|
||||
else
|
||||
eqtype = 'IIR';
|
||||
end
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
fs = 48e3;
|
||||
end
|
||||
|
||||
if nargin < 4 || isempty(f)
|
||||
eq.f = logspace(log10(10),log10(fs/2), 1000);
|
||||
else
|
||||
% Freqz() needs two frequency points or more
|
||||
if length(f) < 2
|
||||
f_single = 1;
|
||||
eq.f = [f f];
|
||||
else
|
||||
f_single = 0;
|
||||
eq.f = f;
|
||||
end
|
||||
end
|
||||
|
||||
if nargin < 5
|
||||
doplot = 1;
|
||||
end
|
||||
|
||||
%% Read blob as 32 bit integers
|
||||
blob = eq_blob_read(blobfn);
|
||||
|
||||
%% Group delay with grpdelay() is not working in Octave
|
||||
do_group_delay = ~exist('OCTAVE_VERSION', 'builtin');
|
||||
|
||||
%% Decode and compute response
|
||||
eq.m = [];
|
||||
eq.gd = [];
|
||||
switch lower(eqtype)
|
||||
case 'fir'
|
||||
hd = eq_fir_blob_decode(blob);
|
||||
eq.m = zeros(length(eq.f), hd.channels_in_config);
|
||||
for i = 1:hd.channels_in_config
|
||||
teq = eq_fir_blob_decode(blob, hd.assign_response(i));
|
||||
h = freqz(teq.b, 1, eq.f, fs);
|
||||
eq.m(:,i) = 20*log10(abs(h));
|
||||
if do_group_delay
|
||||
gd = grpdelay(teq.b, 1, eq.f, fs) / fs;
|
||||
eq.gd(:,i) = gd;
|
||||
end
|
||||
end
|
||||
|
||||
case 'iir'
|
||||
hd = eq_iir_blob_decode(blob);
|
||||
eq.m = zeros(length(eq.f), hd.channels_in_config);
|
||||
for i = 1:hd.channels_in_config
|
||||
teq = eq_iir_blob_decode(blob, hd.assign_response(i));
|
||||
h = freqz(teq.b, teq.a, eq.f, fs);
|
||||
eq.m(:,i) = 20*log10(abs(h));
|
||||
if do_group_delay
|
||||
gd = grpdelay(teq.b, teq.a, eq.f, fs) / fs;
|
||||
eq.gd(:,i) = gd;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%% Optional plots
|
||||
if doplot
|
||||
eq.fh(1) = figure;
|
||||
semilogx(eq.f, eq.m);
|
||||
ymin = max(min(min(eq.m)), -60);
|
||||
ymax = max(max(eq.m));
|
||||
axis([10 round(fs/2/10)*10 ymin-3 ymax+3 ]);
|
||||
grid on;
|
||||
channel_legends(hd.channels_in_config);
|
||||
xlabel('Frequency (Hz)');
|
||||
ylabel('Amplitude (dB)');
|
||||
title(blobfn, 'Interpreter', 'None');
|
||||
|
||||
if do_group_delay
|
||||
eq.fh(2) = figure;
|
||||
semilogx(eq.f, eq.gd * 1e6);
|
||||
ax = axis();
|
||||
axis([10 round(fs/2/10)*10 ax(3:4) ]);
|
||||
grid on;
|
||||
channel_legends(hd.channels_in_config);
|
||||
xlabel('Frequency (Hz)');
|
||||
ylabel('Group delay (us)');
|
||||
title(blobfn, 'Interpreter', 'None');
|
||||
end
|
||||
end
|
||||
|
||||
%% Trim avay the duplicated frequency point
|
||||
if f_single
|
||||
eq.f = eq.f(1);
|
||||
if do_group_delay
|
||||
eq.gd = eq.gd(1);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%% Helper functions
|
||||
function channel_legends(n)
|
||||
|
||||
switch n
|
||||
case 2
|
||||
legend('ch1', 'ch2');
|
||||
case 4
|
||||
legend('ch1', 'ch2', 'ch3', 'ch4');
|
||||
case 6
|
||||
legend('ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6');
|
||||
case 8
|
||||
legend('ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8');
|
||||
otherwise
|
||||
error('Illegal number of channels found');
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,69 @@
|
|||
function blob = eq_blob_read(blobfn, fntype)
|
||||
|
||||
% SPDX-License-Identifier: BSD-3-Clause
|
||||
%
|
||||
% Copyright (c) 2020, Intel Corporation. All rights reserved.
|
||||
%
|
||||
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
|
||||
|
||||
%% Use file suffix as type
|
||||
if nargin < 2
|
||||
idx = findstr(blobfn, '.');
|
||||
fntype = blobfn(idx(end)+1:end);
|
||||
end
|
||||
|
||||
%% Read the file
|
||||
switch lower(fntype)
|
||||
case 'bin'
|
||||
fh = fopen(blobfn, 'rb');
|
||||
tmp = fread(fh, inf, 'uint32');
|
||||
fclose(fh);
|
||||
case 'txt'
|
||||
fh = fopen(blobfn, 'r');
|
||||
tmp = fscanf(fh, '%u,', Inf);
|
||||
fclose(fh);
|
||||
case 'm4'
|
||||
tmp = get_parse_m4(blobfn);
|
||||
otherwise
|
||||
error('Illegal file type, please give fntype argument');
|
||||
|
||||
end
|
||||
|
||||
blob = uint32(tmp);
|
||||
|
||||
end
|
||||
|
||||
%% Parse m4 topology blob
|
||||
function blob = get_parse_m4(blobfn)
|
||||
|
||||
fh = fopen(blobfn, 'r');
|
||||
|
||||
% Ignore two lines from beginning
|
||||
ln = fgets(fh);
|
||||
ln = fgets(fh);
|
||||
|
||||
% Loop until end of file
|
||||
n = 1;
|
||||
ln = fgets(fh);
|
||||
while ln ~= -1
|
||||
idx = findstr(ln, '0x');
|
||||
for i = 1:length(idx)
|
||||
bytes(n) = hex2dec(ln(idx(i)+2:idx(i)+3));
|
||||
n = n + 1;
|
||||
end
|
||||
ln = fgets(fh);
|
||||
end
|
||||
fclose(fh);
|
||||
|
||||
% Convert to 32 bit
|
||||
n32 = round(length(bytes)/4);
|
||||
blob = zeros(n32, 1);
|
||||
for i = 1:n32
|
||||
i8 = (i - 1)*4 + 1;
|
||||
blob(i) = bytes(i8) * 2^0 ...
|
||||
+ bytes(i8 + 1) * 2^8 ...
|
||||
+ bytes(i8 + 2) * 2^16 ...
|
||||
+ bytes(i8 + 3) * 2^24;
|
||||
end
|
||||
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
function eq = eq_fir_blob_decode(blobfn, resp_n, fs, do_plot)
|
||||
function eq = eq_fir_blob_decode(blob, resp_n)
|
||||
|
||||
%% Decode a FIR EQ binary blob
|
||||
%
|
||||
|
@ -16,48 +16,22 @@ function eq = eq_fir_blob_decode(blobfn, resp_n, fs, do_plot)
|
|||
% assign_response - vector of EQ indexes assigned to channels
|
||||
% size - length in bytes
|
||||
|
||||
%%
|
||||
% Copyright (c) 2016, Intel Corporation
|
||||
% All rights reserved.
|
||||
% SPDX-License-Identifier: BSD-3-Clause
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are met:
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in the
|
||||
% documentation and/or other materials provided with the distribution.
|
||||
% * Neither the name of the Intel Corporation nor the
|
||||
% names of its contributors may be used to endorse or promote products
|
||||
% derived from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
% Copyright (c) 2016-2020, Intel Corporation. All rights reserved.
|
||||
%
|
||||
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
|
||||
%
|
||||
|
||||
if nargin < 4
|
||||
do_plot = 0;
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
fs = 48e3;
|
||||
end
|
||||
|
||||
if nargin < 2
|
||||
resp_n = 0;
|
||||
verbose = 1;
|
||||
resp_n = [];
|
||||
else
|
||||
verbose = 0;
|
||||
end
|
||||
|
||||
%% Get ABI information
|
||||
[abi_bytes, nbytes_abi] = eq_get_abi(0);
|
||||
|
||||
%% Defaults
|
||||
eq.b = [];
|
||||
eq.a = [];
|
||||
|
@ -65,13 +39,17 @@ eq.channels_in_config = 0;
|
|||
eq.number_of_responses = 0;
|
||||
eq.assign_response = [];
|
||||
|
||||
%% Read binary file
|
||||
fh = fopen(blobfn, 'rb');
|
||||
blob16 = fread(fh, inf, 'int16');
|
||||
fclose(fh);
|
||||
%% Convert to 16 bits
|
||||
blob16 = zeros(1, length(blob)*2);
|
||||
for i = 1:length(blob)
|
||||
i16 = 2*(i - 1) + 1;
|
||||
blob16(i16) = bitand(blob(i), 65535);
|
||||
blob16(i16 + 1) = bitshift(blob(i), -16);
|
||||
end
|
||||
blob16 = signedint(double(blob16), 16);
|
||||
|
||||
%% Decode
|
||||
abi = 16;
|
||||
abi = nbytes_abi / 2;
|
||||
eq.size = blob16(abi + 1) + 65536*blob16(abi + 2);
|
||||
eq.channels_in_config = blob16(abi + 3);
|
||||
eq.number_of_responses = blob16(abi + 4);
|
||||
|
@ -85,15 +63,31 @@ reserved7 = blob16(abi + 11);
|
|||
reserved8 = blob16(abi + 12);
|
||||
eq.assign_response = blob16(abi + 13:abi + 13 + eq.channels_in_config-1);
|
||||
|
||||
fprintf('Blob size = %d\n', eq.size);
|
||||
fprintf('Channels in config = %d\n', eq.channels_in_config);
|
||||
fprintf('Number of responses = %d\n', eq.number_of_responses);
|
||||
fprintf('Assign responses =');
|
||||
for i=1:length(eq.assign_response)
|
||||
fprintf(' %d', eq.assign_response(i));
|
||||
if verbose
|
||||
fprintf('Blob size = %d\n', eq.size);
|
||||
fprintf('Channels in config = %d\n', eq.channels_in_config);
|
||||
fprintf('Number of responses = %d\n', eq.number_of_responses);
|
||||
fprintf('Assign responses =');
|
||||
for i=1:length(eq.assign_response)
|
||||
fprintf(' %d', eq.assign_response(i));
|
||||
end
|
||||
fprintf('\n');
|
||||
end
|
||||
fprintf('\n');
|
||||
|
||||
% Just header request
|
||||
if isempty(resp_n)
|
||||
eq.b = [];
|
||||
eq.a = [];
|
||||
return
|
||||
end
|
||||
|
||||
% Handle pass-through
|
||||
if resp_n < 0
|
||||
eq.b = 1;
|
||||
eq.a = 1;
|
||||
end
|
||||
|
||||
% Normal filter taps retrieve
|
||||
if resp_n > eq.number_of_responses-1;
|
||||
error('Request of non-available response');
|
||||
end
|
||||
|
@ -104,24 +98,19 @@ b16 = blob16(abi + n_blob_header + eq.channels_in_config + 1:end);
|
|||
j = 1;
|
||||
for i=1:eq.number_of_responses
|
||||
filter_length = b16(j);
|
||||
output_shift = b16(j+1);
|
||||
output_shift = double(b16(j+1));
|
||||
if i-1 == resp_n
|
||||
bi = b16(j+n_fir_header:j+n_fir_header+filter_length-1);
|
||||
eq.b = 2^(-output_shift)*double(bi)/32768;
|
||||
eq.b = 2^(-output_shift)*bi/32768;
|
||||
end
|
||||
j = j+filter_length+n_fir_header;
|
||||
end
|
||||
eq.a = 1;
|
||||
|
||||
if do_plot > 0
|
||||
figure;
|
||||
f = logspace(log10(10),log10(fs/2), 500);
|
||||
h = freqz(eq.b, eq.a, f, fs);
|
||||
semilogx(f, 20*log10(abs(h)));
|
||||
axis([20 20e3 -40 20]);
|
||||
grid on;
|
||||
xlabel('Frequency (Hz)');
|
||||
ylabel('Amplitude (dB)');
|
||||
end
|
||||
|
||||
function y = signedint(x, bits)
|
||||
y = x;
|
||||
idx = find(x > 2^(bits-1)-1);
|
||||
y(idx) = x(idx)-2^bits;
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
function eq = eq_iir_blob_decode(blobfn, resp_n, fs, do_plot)
|
||||
function eq = eq_iir_blob_decode(ublob, resp_n)
|
||||
|
||||
%% Decode an IIR EQ binary blob
|
||||
%
|
||||
% eq = eq_fir_decode_blob(blobfn, resp_n, fs, do_plot)
|
||||
% eq = eq_fir_decode_blob(blobfn, resp_n)
|
||||
%
|
||||
% blobfn - file name of EQ setup blob
|
||||
% resp_n - index of response to decode
|
||||
|
@ -16,48 +16,22 @@ function eq = eq_iir_blob_decode(blobfn, resp_n, fs, do_plot)
|
|||
% assign response - vector of EQ indexes assigned to channels
|
||||
%
|
||||
|
||||
%%
|
||||
% Copyright (c) 2016, Intel Corporation
|
||||
% All rights reserved.
|
||||
% SPDX-License-Identifier: BSD-3-Clause
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are met:
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in the
|
||||
% documentation and/or other materials provided with the distribution.
|
||||
% * Neither the name of the Intel Corporation nor the
|
||||
% names of its contributors may be used to endorse or promote products
|
||||
% derived from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
% Copyright (c) 2016-2020, Intel Corporation. All rights reserved.
|
||||
%
|
||||
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
|
||||
%
|
||||
|
||||
if nargin < 4
|
||||
do_plot = 0;
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
fs = 48e3;
|
||||
end
|
||||
|
||||
if nargin < 2
|
||||
resp_n = 0;
|
||||
verbose = 1;
|
||||
resp_n = [];
|
||||
else
|
||||
verbose = 0;
|
||||
end
|
||||
|
||||
%% Get ABI information
|
||||
[abi_bytes, nbytes_abi] = eq_get_abi(0);
|
||||
|
||||
%% Defaults
|
||||
eq.b = [];
|
||||
eq.a = [];
|
||||
|
@ -65,13 +39,9 @@ eq.channels_in_config = 0;
|
|||
eq.number_of_responses = 0;
|
||||
eq.assign_response = [];
|
||||
|
||||
%% Read binary file
|
||||
fh = fopen(blobfn, 'rb');
|
||||
blob = fread(fh, inf, 'uint32');
|
||||
fclose(fh);
|
||||
|
||||
%% Decode
|
||||
abi = 8;
|
||||
blob = double(ublob);
|
||||
abi = nbytes_abi / 4;
|
||||
eq.size = blob(abi + 1);
|
||||
eq.channels_in_config = blob(abi + 2);
|
||||
eq.number_of_responses = blob(abi + 3);
|
||||
|
@ -79,17 +49,33 @@ reserved1 = blob(abi + 4);
|
|||
reserved2 = blob(abi + 5);
|
||||
reserved3 = blob(abi + 6);
|
||||
reserved4 = blob(abi + 7);
|
||||
eq.assign_response = blob(abi + 8:abi + 8 + eq.channels_in_config - 1);
|
||||
eq.assign_response = signedint(blob(abi + 8:abi + 8 + eq.channels_in_config - 1), 32);
|
||||
|
||||
fprintf('Blob size = %d\n', eq.size);
|
||||
fprintf('Channels in config = %d\n', eq.channels_in_config);
|
||||
fprintf('Number of responses = %d\n', eq.number_of_responses);
|
||||
fprintf('Assign responses =');
|
||||
for i=1:length(eq.assign_response)
|
||||
fprintf(' %d', eq.assign_response(i));
|
||||
if verbose
|
||||
fprintf('Blob size = %d\n', eq.size);
|
||||
fprintf('Channels in config = %d\n', eq.channels_in_config);
|
||||
fprintf('Number of responses = %d\n', eq.number_of_responses);
|
||||
fprintf('Assign responses =');
|
||||
for i=1:length(eq.assign_response)
|
||||
fprintf(' %d', eq.assign_response(i));
|
||||
end
|
||||
fprintf('\n');
|
||||
end
|
||||
fprintf('\n');
|
||||
|
||||
% Just header request
|
||||
if isempty(resp_n)
|
||||
eq.b = [];
|
||||
eq.a = [];
|
||||
return
|
||||
end
|
||||
|
||||
% Handle pass-through
|
||||
if resp_n < 0
|
||||
eq.b = 1;
|
||||
eq.a = 1;
|
||||
end
|
||||
|
||||
% Normal filter taps retrieve
|
||||
if resp_n > eq.number_of_responses-1;
|
||||
error('Request of non-available response');
|
||||
end
|
||||
|
@ -98,7 +84,6 @@ n_blob_header = 7;
|
|||
n_iir_header = 6;
|
||||
n_iir_section = 7;
|
||||
|
||||
f = logspace(log10(10),log10(fs/2), 500);
|
||||
j = abi + n_blob_header + eq.channels_in_config + 1;
|
||||
eq.b = 1.0;
|
||||
eq.a = 1.0;
|
||||
|
@ -116,13 +101,6 @@ for i=1:eq.number_of_responses
|
|||
a0 = [1 -(ai/2^30)];
|
||||
gain = gaini/2^14;
|
||||
b0 = b0 * 2^(-shifti) * gain;
|
||||
if do_plot > 1
|
||||
figure;
|
||||
h = freqz(b0, a0, f, fs);
|
||||
semilogx(f, 20*log10(abs(h)));
|
||||
ax = axis; axis([20 20e3 -40 20]);
|
||||
grid on;
|
||||
end
|
||||
eq.b = conv(eq.b, b0);
|
||||
eq.a = conv(eq.a, a0);
|
||||
k = k + n_iir_section;
|
||||
|
@ -131,16 +109,6 @@ for i=1:eq.number_of_responses
|
|||
j = j+section_length;
|
||||
end
|
||||
|
||||
if do_plot > 0
|
||||
figure;
|
||||
h = freqz(eq.b, eq.a, f, fs);
|
||||
semilogx(f, 20*log10(abs(h)));
|
||||
axis([20 20e3 -40 20]);
|
||||
grid on;
|
||||
xlabel('Frequency (Hz)');
|
||||
ylabel('Amplitude (dB)');
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function y = signedint(x, bits)
|
||||
|
|
Loading…
Reference in New Issue