15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 Google Inc. All Rights Reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// that can be found in the COPYING file in the root of the source
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// tree. An additional intellectual property rights grant can be found
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// in the file PATENTS. All contributing project authors may
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// be found in the AUTHORS file in the root of the source tree.
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// -----------------------------------------------------------------------------
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Pseudo-random utilities
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Author: Skal (pascal.massimino@gmail.com)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef WEBP_UTILS_RANDOM_H_
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define WEBP_UTILS_RANDOM_H_
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <assert.h>
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "../webp/types.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef __cplusplus
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern "C" {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define VP8_RANDOM_DITHER_FIX 8   // fixed-point precision for dithering
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define VP8_RANDOM_TABLE_SIZE 55
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef struct {
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int index1_, index2_;
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t tab_[VP8_RANDOM_TABLE_SIZE];
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int amp_;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} VP8Random;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Initializes random generator with an amplitude 'dithering' in range [0..1].
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VP8InitRandom(VP8Random* const rg, float dithering);
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns a centered pseudo-random number with 'num_bits' amplitude.
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// (uses D.Knuth's Difference-based random generator).
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision.
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits,
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      int amp) {
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int diff;
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31);
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_];
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (diff < 0) diff += (1u << 31);
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  rg->tab_[rg->index1_] = diff;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0;
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // sign-extend, 0-center
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  diff = (int)((uint32_t)diff << 1) >> (32 - num_bits);
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX;  // restrict range
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  diff += 1 << (num_bits - 1);                   // shift back to 0.5-center
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return diff;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) {
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return VP8RandomBits2(rg, num_bits, rg->amp_);
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef __cplusplus
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}    // extern "C"
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  /* WEBP_UTILS_RANDOM_H_ */
64