void shade(const Scene * scene, const int level, const C_FLT weight, const Ray &ray, Intercept * intercepts, Color * color) { Material * entryMat = intercepts[0].material, * hitMat = intercepts[0].enter? intercepts[0].primitive->material: ray.medium; C_FLT specWeight = hitMat->specular.magnitude() * weight, transWeight = hitMat->transmission.magnitude() * weight; Vector3D specDir, transDir, normal; std::vector<P_FLT> mapping; Point3D interceptPoint = ray.rayPoint(intercepts[0].t); intercepts[0].primitive->getIntersect(interceptPoint, &normal, &mapping); if (dotProduct(ray.dir, normal) > 0.0f) { normal.negate(); } specularDirection(ray.dir, normal, &specDir); bool transmission = transmissionDirection(entryMat, hitMat, ray.dir, normal, &transDir); *color += scene->ambience * hitMat->ambience; for (std::vector<Light *>::const_iterator itr = scene->lights.begin(); itr != scene->lights.end(); itr++) { Vector3D pointToLight = (*itr)->orig - interceptPoint; P_FLT distanceToLight = pointToLight.normalize(); Ray rayToLight(interceptPoint, pointToLight, NULL); P_FLT lightDotNormal = dotProduct(pointToLight, normal); if (fGreaterZero(lightDotNormal) && fGreaterZero(shadow(scene, rayToLight, distanceToLight))) { // Light source diffuse reflection *color += (*itr)->color * hitMat->diffuse * lightDotNormal; // Light source specular reflection Vector3D h = pointToLight - ray.dir; h.normalize(); P_FLT specDot = dotProduct(normal, h); if (specDot > 0.0f) { *color += (*itr)->color * hitMat->specular * pow(specDot, hitMat->shine); } } else if (transmission && fLessZero(lightDotNormal) && fLessZero(shadow(scene, rayToLight, distanceToLight))) { // Light source specular transmission C_FLT refrRatio = hitMat->refraction / entryMat->refraction; if (!fEqual(refrRatio, 1.0f)) { Vector3D h_j = (-ray.dir - pointToLight * refrRatio) / (refrRatio - 1); h_j.normalize(); // TODO(kent): Define transmission highlight coefficient *color += (*itr)->color * hitMat->transmission * pow(dotProduct(-normal, h_j), hitMat->shine); } } } if (level < MAX_LEVEL) { // Other body specular reflection if (specWeight > MIN_WEIGHT) { Ray specRay(interceptPoint, specDir, entryMat); Color specColor; trace(scene, level + 1, specWeight, specRay, &specColor); *color += specColor * hitMat->specular; } // Other body specular transmission if (transWeight > MIN_WEIGHT) { if (transmission) { Ray transRay(interceptPoint, transDir, hitMat); Color transColor; trace(scene, level + 1, transWeight, transRay, &transColor); *color += transColor * hitMat->transmission; } else { // TODO(kent): Handle total internal reflection } } } if (intercepts[0].enter && intercepts[0].primitive->texture != NULL) { *color *= intercepts[0].primitive->getTexColor(mapping); } }
bool XSFPlayer::FillBuffer(std::vector<uint8_t> &buf, unsigned &samplesWritten) { bool endFlag = false; unsigned detectSilence = xSFConfig->GetDetectSilenceSec(); unsigned pos = 0, bufsize = buf.size() >> 2; auto trueBuffer = std::vector<uint8_t>(bufsize << (this->uses32BitSamplesClampedTo16Bit ? 3 : 2)); auto longBuffer = std::vector<uint8_t>(bufsize << 3); auto bufLong = reinterpret_cast<int32_t *>(&longBuffer[0]); while (pos < bufsize) { unsigned remain = bufsize - pos, offset = pos; this->GenerateSamples(trueBuffer, pos << (this->uses32BitSamplesClampedTo16Bit ? 2 : 1), remain); if (this->uses32BitSamplesClampedTo16Bit) { auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); std::copy_n(&trueBufLong[0], bufsize << 1, &bufLong[0]); } else { auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); std::copy_n(&trueBufShort[0], bufsize << 1, &bufLong[0]); } if (detectSilence || skipSilenceOnStartSec) { unsigned skipOffset = 0; for (unsigned ofs = 0; ofs < remain; ++ofs) { uint32_t sampleL = bufLong[2 * (offset + ofs)], sampleR = bufLong[2 * (offset + ofs) + 1]; bool silence = (sampleL + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleL <= CHECK_SILENCE_LEVEL * 2 && (sampleR + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL) - this->prevSampleR <= CHECK_SILENCE_LEVEL * 2; if (silence) { if (++this->detectedSilenceSample >= this->sampleRate) { this->detectedSilenceSample -= this->sampleRate; ++this->detectedSilenceSec; if (this->skipSilenceOnStartSec && this->detectedSilenceSec >= this->skipSilenceOnStartSec) { this->skipSilenceOnStartSec = this->detectedSilenceSec = 0; if (ofs) skipOffset = ofs; } } } else { this->detectedSilenceSample = this->detectedSilenceSec = 0; if (this->skipSilenceOnStartSec) { this->skipSilenceOnStartSec = 0; if (ofs) skipOffset = ofs; } } prevSampleL = sampleL + CHECK_SILENCE_BIAS; prevSampleR = sampleR + CHECK_SILENCE_BIAS; } if (!this->skipSilenceOnStartSec) { if (skipOffset) { auto tmpBuf = std::vector<int32_t>((bufsize - skipOffset) << 1); std::copy(&bufLong[(offset + skipOffset) << 1], &bufLong[bufsize << 1], &tmpBuf[0]); std::copy_n(&tmpBuf[0], (bufsize - skipOffset) << 1, &bufLong[offset << 1]); pos += skipOffset; } else pos += remain; } } else pos += remain; if (pos < bufsize) { if (this->uses32BitSamplesClampedTo16Bit) { auto trueBufLong = reinterpret_cast<int32_t *>(&trueBuffer[0]); std::copy_n(&bufLong[0], bufsize << 1, &trueBufLong[0]); } else { auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); std::copy_n(&bufLong[0], bufsize << 1, &trueBufShort[0]); } } } /* Detect end of song */ if (!xSFConfig->GetPlayInfinitely()) { if (this->currentSample >= this->lengthSample + this->fadeSample) { samplesWritten = 0; return true; } if (this->currentSample + bufsize >= this->lengthSample + this->fadeSample) { bufsize = this->lengthSample + this->fadeSample - this->currentSample; endFlag = true; } } /* Volume */ if (!this->ignoreVolume && (!fEqual(this->volume, 1.0) || !fEqual(xSFConfig->GetVolume(), 1.0))) { double scale = this->volume * xSFConfig->GetVolume(); for (unsigned ofs = 0; ofs < bufsize; ++ofs) { double s1 = bufLong[2 * ofs] * scale, s2 = bufLong[2 * ofs + 1] * scale; if (!this->uses32BitSamplesClampedTo16Bit) { clamp(s1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); clamp(s2, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); } bufLong[2 * ofs] = static_cast<int32_t>(s1); bufLong[2 * ofs + 1] = static_cast<int32_t>(s2); } } if (this->uses32BitSamplesClampedTo16Bit) { auto bufShort = reinterpret_cast<int16_t *>(&buf[0]); for (unsigned ofs = 0; ofs < bufsize; ++ofs) { int32_t s1 = bufLong[2 * ofs], s2 = bufLong[2 * ofs + 1]; clamp(s1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); clamp(s2, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()); bufShort[2 * ofs] = static_cast<int16_t>(s1); bufShort[2 * ofs + 1] = static_cast<int16_t>(s2); } } else { auto trueBufShort = reinterpret_cast<int16_t *>(&trueBuffer[0]); std::copy_n(&bufLong[0], bufsize << 1, &trueBufShort[0]); std::copy(&trueBuffer[0], &trueBuffer[bufsize << 2], &buf[0]); } /* Fading */ if (!xSFConfig->GetPlayInfinitely() && this->fadeSample && this->currentSample + bufsize >= this->lengthSample) { auto bufShort = reinterpret_cast<int16_t *>(&buf[0]); for (unsigned ofs = 0; ofs < bufsize; ++ofs) { if (this->currentSample + ofs >= this->lengthSample && this->currentSample + ofs < this->lengthSample + this->fadeSample) { int scale = static_cast<uint64_t>(this->lengthSample + this->fadeSample - (this->currentSample + ofs)) * 0x10000 / this->fadeSample; bufShort[2 * ofs] = (bufShort[2 * ofs] * scale) >> 16; bufShort[2 * ofs + 1] = (bufShort[2 * ofs + 1] * scale) >> 16; } else if (this->currentSample + ofs >= this->lengthSample + this->fadeSample)
static float sinc(float x) { return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI); }