123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844 |
- // basisu_resampler.cpp
- // Copyright (C) 2019 Binomial LLC. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "basisu_resampler.h"
- #include "basisu_resampler_filters.h"
- #define RESAMPLER_DEBUG 0
- namespace basisu
- {
- static inline int resampler_range_check(int v, int h)
- {
- BASISU_NOTE_UNUSED(h);
- assert((v >= 0) && (v < h));
- return v;
- }
- // Float to int cast with truncation.
- static inline int cast_to_int(Resample_Real i)
- {
- return (int)i;
- }
- // Ensure that the contributing source sample is within bounds. If not, reflect, clamp, or wrap.
- int Resampler::reflect(const int j, const int src_x, const Boundary_Op boundary_op)
- {
- int n;
- if (j < 0)
- {
- if (boundary_op == BOUNDARY_REFLECT)
- {
- n = -j;
- if (n >= src_x)
- n = src_x - 1;
- }
- else if (boundary_op == BOUNDARY_WRAP)
- n = posmod(j, src_x);
- else
- n = 0;
- }
- else if (j >= src_x)
- {
- if (boundary_op == BOUNDARY_REFLECT)
- {
- n = (src_x - j) + (src_x - 1);
- if (n < 0)
- n = 0;
- }
- else if (boundary_op == BOUNDARY_WRAP)
- n = posmod(j, src_x);
- else
- n = src_x - 1;
- }
- else
- n = j;
- return n;
- }
- // The make_clist() method generates, for all destination samples,
- // the list of all source samples with non-zero weighted contributions.
- Resampler::Contrib_List * Resampler::make_clist(
- int src_x, int dst_x, Boundary_Op boundary_op,
- Resample_Real(*Pfilter)(Resample_Real),
- Resample_Real filter_support,
- Resample_Real filter_scale,
- Resample_Real src_ofs)
- {
- struct Contrib_Bounds
- {
- // The center of the range in DISCRETE coordinates (pixel center = 0.0f).
- Resample_Real center;
- int left, right;
- };
- int i, j, k, n, left, right;
- Resample_Real total_weight;
- Resample_Real xscale, center, half_width, weight;
- Contrib_List* Pcontrib;
- Contrib* Pcpool;
- Contrib* Pcpool_next;
- Contrib_Bounds* Pcontrib_bounds;
- if ((Pcontrib = (Contrib_List*)calloc(dst_x, sizeof(Contrib_List))) == NULL)
- return NULL;
- Pcontrib_bounds = (Contrib_Bounds*)calloc(dst_x, sizeof(Contrib_Bounds));
- if (!Pcontrib_bounds)
- {
- free(Pcontrib);
- return (NULL);
- }
- const Resample_Real oo_filter_scale = 1.0f / filter_scale;
- const Resample_Real NUDGE = 0.5f;
- xscale = dst_x / (Resample_Real)src_x;
- if (xscale < 1.0f)
- {
- int total;
- (void)total;
- // Handle case when there are fewer destination samples than source samples (downsampling/minification).
- // stretched half width of filter
- half_width = (filter_support / xscale) * filter_scale;
- // Find the range of source sample(s) that will contribute to each destination sample.
- for (i = 0, n = 0; i < dst_x; i++)
- {
- // Convert from discrete to continuous coordinates, scale, then convert back to discrete.
- center = ((Resample_Real)i + NUDGE) / xscale;
- center -= NUDGE;
- center += src_ofs;
- left = cast_to_int((Resample_Real)floor(center - half_width));
- right = cast_to_int((Resample_Real)ceil(center + half_width));
- Pcontrib_bounds[i].center = center;
- Pcontrib_bounds[i].left = left;
- Pcontrib_bounds[i].right = right;
- n += (right - left + 1);
- }
- // Allocate memory for contributors.
- if ((n == 0) || ((Pcpool = (Contrib*)calloc(n, sizeof(Contrib))) == NULL))
- {
- free(Pcontrib);
- free(Pcontrib_bounds);
- return NULL;
- }
- total = n;
- Pcpool_next = Pcpool;
- // Create the list of source samples which contribute to each destination sample.
- for (i = 0; i < dst_x; i++)
- {
- int max_k = -1;
- Resample_Real max_w = -1e+20f;
- center = Pcontrib_bounds[i].center;
- left = Pcontrib_bounds[i].left;
- right = Pcontrib_bounds[i].right;
- Pcontrib[i].n = 0;
- Pcontrib[i].p = Pcpool_next;
- Pcpool_next += (right - left + 1);
- assert((Pcpool_next - Pcpool) <= total);
- total_weight = 0;
- for (j = left; j <= right; j++)
- total_weight += (*Pfilter)((center - (Resample_Real)j) * xscale * oo_filter_scale);
- const Resample_Real norm = static_cast<Resample_Real>(1.0f / total_weight);
- total_weight = 0;
- #if RESAMPLER_DEBUG
- printf("%i: ", i);
- #endif
- for (j = left; j <= right; j++)
- {
- weight = (*Pfilter)((center - (Resample_Real)j) * xscale * oo_filter_scale) * norm;
- if (weight == 0.0f)
- continue;
- n = reflect(j, src_x, boundary_op);
- #if RESAMPLER_DEBUG
- printf("%i(%f), ", n, weight);
- #endif
- // Increment the number of source samples which contribute to the current destination sample.
- k = Pcontrib[i].n++;
- Pcontrib[i].p[k].pixel = (unsigned short)n; /* store src sample number */
- Pcontrib[i].p[k].weight = weight; /* store src sample weight */
- total_weight += weight; /* total weight of all contributors */
- if (weight > max_w)
- {
- max_w = weight;
- max_k = k;
- }
- }
- #if RESAMPLER_DEBUG
- printf("\n\n");
- #endif
- //assert(Pcontrib[i].n);
- //assert(max_k != -1);
- if ((max_k == -1) || (Pcontrib[i].n == 0))
- {
- free(Pcpool);
- free(Pcontrib);
- free(Pcontrib_bounds);
- return NULL;
- }
- if (total_weight != 1.0f)
- Pcontrib[i].p[max_k].weight += 1.0f - total_weight;
- }
- }
- else
- {
- // Handle case when there are more destination samples than source samples (upsampling).
- half_width = filter_support * filter_scale;
- // Find the source sample(s) that contribute to each destination sample.
- for (i = 0, n = 0; i < dst_x; i++)
- {
- // Convert from discrete to continuous coordinates, scale, then convert back to discrete.
- center = ((Resample_Real)i + NUDGE) / xscale;
- center -= NUDGE;
- center += src_ofs;
- left = cast_to_int((Resample_Real)floor(center - half_width));
- right = cast_to_int((Resample_Real)ceil(center + half_width));
- Pcontrib_bounds[i].center = center;
- Pcontrib_bounds[i].left = left;
- Pcontrib_bounds[i].right = right;
- n += (right - left + 1);
- }
- /* Allocate memory for contributors. */
- int total = n;
- if ((total == 0) || ((Pcpool = (Contrib*)calloc(total, sizeof(Contrib))) == NULL))
- {
- free(Pcontrib);
- free(Pcontrib_bounds);
- return NULL;
- }
- Pcpool_next = Pcpool;
- // Create the list of source samples which contribute to each destination sample.
- for (i = 0; i < dst_x; i++)
- {
- int max_k = -1;
- Resample_Real max_w = -1e+20f;
- center = Pcontrib_bounds[i].center;
- left = Pcontrib_bounds[i].left;
- right = Pcontrib_bounds[i].right;
- Pcontrib[i].n = 0;
- Pcontrib[i].p = Pcpool_next;
- Pcpool_next += (right - left + 1);
- assert((Pcpool_next - Pcpool) <= total);
- total_weight = 0;
- for (j = left; j <= right; j++)
- total_weight += (*Pfilter)((center - (Resample_Real)j) * oo_filter_scale);
- const Resample_Real norm = static_cast<Resample_Real>(1.0f / total_weight);
- total_weight = 0;
- #if RESAMPLER_DEBUG
- printf("%i: ", i);
- #endif
- for (j = left; j <= right; j++)
- {
- weight = (*Pfilter)((center - (Resample_Real)j) * oo_filter_scale) * norm;
- if (weight == 0.0f)
- continue;
- n = reflect(j, src_x, boundary_op);
- #if RESAMPLER_DEBUG
- printf("%i(%f), ", n, weight);
- #endif
- // Increment the number of source samples which contribute to the current destination sample.
- k = Pcontrib[i].n++;
- Pcontrib[i].p[k].pixel = (unsigned short)n; /* store src sample number */
- Pcontrib[i].p[k].weight = weight; /* store src sample weight */
- total_weight += weight; /* total weight of all contributors */
- if (weight > max_w)
- {
- max_w = weight;
- max_k = k;
- }
- }
- #if RESAMPLER_DEBUG
- printf("\n\n");
- #endif
- //assert(Pcontrib[i].n);
- //assert(max_k != -1);
- if ((max_k == -1) || (Pcontrib[i].n == 0))
- {
- free(Pcpool);
- free(Pcontrib);
- free(Pcontrib_bounds);
- return NULL;
- }
- if (total_weight != 1.0f)
- Pcontrib[i].p[max_k].weight += 1.0f - total_weight;
- }
- }
- #if RESAMPLER_DEBUG
- printf("*******\n");
- #endif
- free(Pcontrib_bounds);
- return Pcontrib;
- }
- void Resampler::resample_x(Sample * Pdst, const Sample * Psrc)
- {
- assert(Pdst);
- assert(Psrc);
- int i, j;
- Sample total;
- Contrib_List* Pclist = m_Pclist_x;
- Contrib* p;
- for (i = m_resample_dst_x; i > 0; i--, Pclist++)
- {
- #if BASISU_RESAMPLER_DEBUG_OPS
- total_ops += Pclist->n;
- #endif
- for (j = Pclist->n, p = Pclist->p, total = 0; j > 0; j--, p++)
- total += Psrc[p->pixel] * p->weight;
- *Pdst++ = total;
- }
- }
- void Resampler::scale_y_mov(Sample * Ptmp, const Sample * Psrc, Resample_Real weight, int dst_x)
- {
- int i;
- #if BASISU_RESAMPLER_DEBUG_OPS
- total_ops += dst_x;
- #endif
- // Not += because temp buf wasn't cleared.
- for (i = dst_x; i > 0; i--)
- * Ptmp++ = *Psrc++ * weight;
- }
- void Resampler::scale_y_add(Sample * Ptmp, const Sample * Psrc, Resample_Real weight, int dst_x)
- {
- #if BASISU_RESAMPLER_DEBUG_OPS
- total_ops += dst_x;
- #endif
- for (int i = dst_x; i > 0; i--)
- (*Ptmp++) += *Psrc++ * weight;
- }
- void Resampler::clamp(Sample * Pdst, int n)
- {
- while (n > 0)
- {
- Sample x = *Pdst;
- *Pdst++ = clamp_sample(x);
- n--;
- }
- }
- void Resampler::resample_y(Sample * Pdst)
- {
- int i, j;
- Sample* Psrc;
- Contrib_List* Pclist = &m_Pclist_y[m_cur_dst_y];
- Sample* Ptmp = m_delay_x_resample ? m_Ptmp_buf : Pdst;
- assert(Ptmp);
- /* Process each contributor. */
- for (i = 0; i < Pclist->n; i++)
- {
- // locate the contributor's location in the scan buffer -- the contributor must always be found!
- for (j = 0; j < MAX_SCAN_BUF_SIZE; j++)
- if (m_Pscan_buf->scan_buf_y[j] == Pclist->p[i].pixel)
- break;
- assert(j < MAX_SCAN_BUF_SIZE);
- Psrc = m_Pscan_buf->scan_buf_l[j];
- if (!i)
- scale_y_mov(Ptmp, Psrc, Pclist->p[i].weight, m_intermediate_x);
- else
- scale_y_add(Ptmp, Psrc, Pclist->p[i].weight, m_intermediate_x);
- /* If this source line doesn't contribute to any
- * more destination lines then mark the scanline buffer slot
- * which holds this source line as free.
- * (The max. number of slots used depends on the Y
- * axis sampling factor and the scaled filter width.)
- */
- if (--m_Psrc_y_count[resampler_range_check(Pclist->p[i].pixel, m_resample_src_y)] == 0)
- {
- m_Psrc_y_flag[resampler_range_check(Pclist->p[i].pixel, m_resample_src_y)] = false;
- m_Pscan_buf->scan_buf_y[j] = -1;
- }
- }
- /* Now generate the destination line */
- if (m_delay_x_resample) // Was X resampling delayed until after Y resampling?
- {
- assert(Pdst != Ptmp);
- resample_x(Pdst, Ptmp);
- }
- else
- {
- assert(Pdst == Ptmp);
- }
- if (m_lo < m_hi)
- clamp(Pdst, m_resample_dst_x);
- }
- bool Resampler::put_line(const Sample * Psrc)
- {
- int i;
- if (m_cur_src_y >= m_resample_src_y)
- return false;
- /* Does this source line contribute
- * to any destination line? if not,
- * exit now.
- */
- if (!m_Psrc_y_count[resampler_range_check(m_cur_src_y, m_resample_src_y)])
- {
- m_cur_src_y++;
- return true;
- }
- /* Find an empty slot in the scanline buffer. (FIXME: Perf. is terrible here with extreme scaling ratios.) */
- for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
- if (m_Pscan_buf->scan_buf_y[i] == -1)
- break;
- /* If the buffer is full, exit with an error. */
- if (i == MAX_SCAN_BUF_SIZE)
- {
- m_status = STATUS_SCAN_BUFFER_FULL;
- return false;
- }
- m_Psrc_y_flag[resampler_range_check(m_cur_src_y, m_resample_src_y)] = true;
- m_Pscan_buf->scan_buf_y[i] = m_cur_src_y;
- /* Does this slot have any memory allocated to it? */
- if (!m_Pscan_buf->scan_buf_l[i])
- {
- if ((m_Pscan_buf->scan_buf_l[i] = (Sample*)malloc(m_intermediate_x * sizeof(Sample))) == NULL)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return false;
- }
- }
- // Resampling on the X axis first?
- if (m_delay_x_resample)
- {
- assert(m_intermediate_x == m_resample_src_x);
- // Y-X resampling order
- memcpy(m_Pscan_buf->scan_buf_l[i], Psrc, m_intermediate_x * sizeof(Sample));
- }
- else
- {
- assert(m_intermediate_x == m_resample_dst_x);
- // X-Y resampling order
- resample_x(m_Pscan_buf->scan_buf_l[i], Psrc);
- }
- m_cur_src_y++;
- return true;
- }
- const Resampler::Sample* Resampler::get_line()
- {
- int i;
- /* If all the destination lines have been
- * generated, then always return NULL.
- */
- if (m_cur_dst_y == m_resample_dst_y)
- return NULL;
- /* Check to see if all the required
- * contributors are present, if not,
- * return NULL.
- */
- for (i = 0; i < m_Pclist_y[m_cur_dst_y].n; i++)
- if (!m_Psrc_y_flag[resampler_range_check(m_Pclist_y[m_cur_dst_y].p[i].pixel, m_resample_src_y)])
- return NULL;
- resample_y(m_Pdst_buf);
- m_cur_dst_y++;
- return m_Pdst_buf;
- }
- Resampler::~Resampler()
- {
- int i;
- #if BASISU_RESAMPLER_DEBUG_OPS
- printf("actual ops: %i\n", total_ops);
- #endif
- free(m_Pdst_buf);
- m_Pdst_buf = NULL;
- if (m_Ptmp_buf)
- {
- free(m_Ptmp_buf);
- m_Ptmp_buf = NULL;
- }
- /* Don't deallocate a contibutor list
- * if the user passed us one of their own.
- */
- if ((m_Pclist_x) && (!m_clist_x_forced))
- {
- free(m_Pclist_x->p);
- free(m_Pclist_x);
- m_Pclist_x = NULL;
- }
- if ((m_Pclist_y) && (!m_clist_y_forced))
- {
- free(m_Pclist_y->p);
- free(m_Pclist_y);
- m_Pclist_y = NULL;
- }
- free(m_Psrc_y_count);
- m_Psrc_y_count = NULL;
- free(m_Psrc_y_flag);
- m_Psrc_y_flag = NULL;
- if (m_Pscan_buf)
- {
- for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
- free(m_Pscan_buf->scan_buf_l[i]);
- free(m_Pscan_buf);
- m_Pscan_buf = NULL;
- }
- }
- void Resampler::restart()
- {
- if (STATUS_OKAY != m_status)
- return;
- m_cur_src_y = m_cur_dst_y = 0;
- int i, j;
- for (i = 0; i < m_resample_src_y; i++)
- {
- m_Psrc_y_count[i] = 0;
- m_Psrc_y_flag[i] = false;
- }
- for (i = 0; i < m_resample_dst_y; i++)
- {
- for (j = 0; j < m_Pclist_y[i].n; j++)
- m_Psrc_y_count[resampler_range_check(m_Pclist_y[i].p[j].pixel, m_resample_src_y)]++;
- }
- for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
- {
- m_Pscan_buf->scan_buf_y[i] = -1;
- free(m_Pscan_buf->scan_buf_l[i]);
- m_Pscan_buf->scan_buf_l[i] = NULL;
- }
- }
- Resampler::Resampler(int src_x, int src_y,
- int dst_x, int dst_y,
- Boundary_Op boundary_op,
- Resample_Real sample_low, Resample_Real sample_high,
- const char* Pfilter_name,
- Contrib_List * Pclist_x,
- Contrib_List * Pclist_y,
- Resample_Real filter_x_scale,
- Resample_Real filter_y_scale,
- Resample_Real src_x_ofs,
- Resample_Real src_y_ofs)
- {
- int i, j;
- Resample_Real support, (*func)(Resample_Real);
- assert(src_x > 0);
- assert(src_y > 0);
- assert(dst_x > 0);
- assert(dst_y > 0);
- #if BASISU_RESAMPLER_DEBUG_OPS
- total_ops = 0;
- #endif
- m_lo = sample_low;
- m_hi = sample_high;
- m_delay_x_resample = false;
- m_intermediate_x = 0;
- m_Pdst_buf = NULL;
- m_Ptmp_buf = NULL;
- m_clist_x_forced = false;
- m_Pclist_x = NULL;
- m_clist_y_forced = false;
- m_Pclist_y = NULL;
- m_Psrc_y_count = NULL;
- m_Psrc_y_flag = NULL;
- m_Pscan_buf = NULL;
- m_status = STATUS_OKAY;
- m_resample_src_x = src_x;
- m_resample_src_y = src_y;
- m_resample_dst_x = dst_x;
- m_resample_dst_y = dst_y;
- m_boundary_op = boundary_op;
- if ((m_Pdst_buf = (Sample*)malloc(m_resample_dst_x * sizeof(Sample))) == NULL)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return;
- }
- // Find the specified filter.
- if (Pfilter_name == NULL)
- Pfilter_name = BASISU_RESAMPLER_DEFAULT_FILTER;
- for (i = 0; i < g_num_resample_filters; i++)
- if (strcmp(Pfilter_name, g_resample_filters[i].name) == 0)
- break;
- if (i == g_num_resample_filters)
- {
- m_status = STATUS_BAD_FILTER_NAME;
- return;
- }
- func = g_resample_filters[i].func;
- support = g_resample_filters[i].support;
- /* Create contributor lists, unless the user supplied custom lists. */
- if (!Pclist_x)
- {
- m_Pclist_x = make_clist(m_resample_src_x, m_resample_dst_x, m_boundary_op, func, support, filter_x_scale, src_x_ofs);
- if (!m_Pclist_x)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return;
- }
- }
- else
- {
- m_Pclist_x = Pclist_x;
- m_clist_x_forced = true;
- }
- if (!Pclist_y)
- {
- m_Pclist_y = make_clist(m_resample_src_y, m_resample_dst_y, m_boundary_op, func, support, filter_y_scale, src_y_ofs);
- if (!m_Pclist_y)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return;
- }
- }
- else
- {
- m_Pclist_y = Pclist_y;
- m_clist_y_forced = true;
- }
- if ((m_Psrc_y_count = (int*)calloc(m_resample_src_y, sizeof(int))) == NULL)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return;
- }
- if ((m_Psrc_y_flag = (unsigned char*)calloc(m_resample_src_y, sizeof(unsigned char))) == NULL)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return;
- }
- // Count how many times each source line contributes to a destination line.
- for (i = 0; i < m_resample_dst_y; i++)
- for (j = 0; j < m_Pclist_y[i].n; j++)
- m_Psrc_y_count[resampler_range_check(m_Pclist_y[i].p[j].pixel, m_resample_src_y)]++;
- if ((m_Pscan_buf = (Scan_Buf*)malloc(sizeof(Scan_Buf))) == NULL)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return;
- }
- for (i = 0; i < MAX_SCAN_BUF_SIZE; i++)
- {
- m_Pscan_buf->scan_buf_y[i] = -1;
- m_Pscan_buf->scan_buf_l[i] = NULL;
- }
- m_cur_src_y = m_cur_dst_y = 0;
- {
- // Determine which axis to resample first by comparing the number of multiplies required
- // for each possibility.
- int x_ops = count_ops(m_Pclist_x, m_resample_dst_x);
- int y_ops = count_ops(m_Pclist_y, m_resample_dst_y);
- // Hack 10/2000: Weight Y axis ops a little more than X axis ops.
- // (Y axis ops use more cache resources.)
- int xy_ops = x_ops * m_resample_src_y +
- (4 * y_ops * m_resample_dst_x) / 3;
- int yx_ops = (4 * y_ops * m_resample_src_x) / 3 +
- x_ops * m_resample_dst_y;
- #if BASISU_RESAMPLER_DEBUG_OPS
- printf("src: %i %i\n", m_resample_src_x, m_resample_src_y);
- printf("dst: %i %i\n", m_resample_dst_x, m_resample_dst_y);
- printf("x_ops: %i\n", x_ops);
- printf("y_ops: %i\n", y_ops);
- printf("xy_ops: %i\n", xy_ops);
- printf("yx_ops: %i\n", yx_ops);
- #endif
- // Now check which resample order is better. In case of a tie, choose the order
- // which buffers the least amount of data.
- if ((xy_ops > yx_ops) ||
- ((xy_ops == yx_ops) && (m_resample_src_x < m_resample_dst_x)))
- {
- m_delay_x_resample = true;
- m_intermediate_x = m_resample_src_x;
- }
- else
- {
- m_delay_x_resample = false;
- m_intermediate_x = m_resample_dst_x;
- }
- #if BASISU_RESAMPLER_DEBUG_OPS
- printf("delaying: %i\n", m_delay_x_resample);
- #endif
- }
- if (m_delay_x_resample)
- {
- if ((m_Ptmp_buf = (Sample*)malloc(m_intermediate_x * sizeof(Sample))) == NULL)
- {
- m_status = STATUS_OUT_OF_MEMORY;
- return;
- }
- }
- }
- void Resampler::get_clists(Contrib_List * *ptr_clist_x, Contrib_List * *ptr_clist_y)
- {
- if (ptr_clist_x)
- * ptr_clist_x = m_Pclist_x;
- if (ptr_clist_y)
- * ptr_clist_y = m_Pclist_y;
- }
- int Resampler::get_filter_num()
- {
- return g_num_resample_filters;
- }
- const char* Resampler::get_filter_name(int filter_num)
- {
- if ((filter_num < 0) || (filter_num >= g_num_resample_filters))
- return NULL;
- else
- return g_resample_filters[filter_num].name;
- }
-
- } // namespace basisu
|