Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: third_party/WebKit/Source/platform/audio/AudioBus.cpp

Issue 1773973002: Complete the implementation of up/down-mixing rules for AudioNode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleaning up and removing casting (after l-g-t-m) Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/audio/AudioBus.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 { 209 {
210 for (unsigned i = 0; i < numberOfChannels(); ++i) 210 for (unsigned i = 0; i < numberOfChannels(); ++i)
211 channel(i)->scale(scale); 211 channel(i)->scale(scale);
212 } 212 }
213 213
214 void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channel Interpretation) 214 void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channel Interpretation)
215 { 215 {
216 if (&sourceBus == this) 216 if (&sourceBus == this)
217 return; 217 return;
218 218
219 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 219 // Copying bus is equivalent to zeroing and then summing.
220 unsigned numberOfDestinationChannels = numberOfChannels(); 220 zero();
221 221 sumFrom(sourceBus, channelInterpretation);
222 if (numberOfDestinationChannels == numberOfSourceChannels) {
223 for (unsigned i = 0; i < numberOfSourceChannels; ++i)
224 channel(i)->copyFrom(sourceBus.channel(i));
225 } else {
226 switch (channelInterpretation) {
227 case Speakers:
228 speakersCopyFrom(sourceBus);
229 break;
230 case Discrete:
231 discreteCopyFrom(sourceBus);
232 break;
233 default:
234 ASSERT_NOT_REACHED();
235 }
236 }
237 } 222 }
238 223
239 void AudioBus::sumFrom(const AudioBus& sourceBus, ChannelInterpretation channelI nterpretation) 224 void AudioBus::sumFrom(const AudioBus& sourceBus, ChannelInterpretation channelI nterpretation)
240 { 225 {
241 if (&sourceBus == this) 226 if (&sourceBus == this)
242 return; 227 return;
243 228
244 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 229 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
245 unsigned numberOfDestinationChannels = numberOfChannels(); 230 unsigned numberOfDestinationChannels = numberOfChannels();
246 231
247 if (numberOfDestinationChannels == numberOfSourceChannels) { 232 // If the channel numbers are equal, perform channels-wise summing.
233 if (numberOfSourceChannels == numberOfDestinationChannels) {
248 for (unsigned i = 0; i < numberOfSourceChannels; ++i) 234 for (unsigned i = 0; i < numberOfSourceChannels; ++i)
249 channel(i)->sumFrom(sourceBus.channel(i)); 235 channel(i)->sumFrom(sourceBus.channel(i));
250 } else { 236
251 switch (channelInterpretation) { 237 return;
252 case Speakers: 238 }
253 speakersSumFrom(sourceBus); 239
254 break; 240 // Otherwise perform up/down-mix or the discrete transfer based on the
255 case Discrete: 241 // number of channels and the channel interpretation.
256 discreteSumFrom(sourceBus); 242 switch (channelInterpretation) {
257 break; 243 case Speakers:
258 default: 244 if (numberOfSourceChannels < numberOfDestinationChannels)
259 ASSERT_NOT_REACHED(); 245 sumFromByUpMixing(sourceBus);
260 } 246 else
261 } 247 sumFromByDownMixing(sourceBus);
262 } 248 break;
263 249 case Discrete:
264 void AudioBus::speakersCopyFrom(const AudioBus& sourceBus)
265 {
266 // FIXME: Implement down mixing 5.1 to stereo.
267 // https://bugs.webkit.org/show_bug.cgi?id=79192
268
269 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
270 unsigned numberOfDestinationChannels = numberOfChannels();
271
272 if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) {
273 // Handle mono -> stereo case (for now simply copy mono channel into bot h left and right)
274 // FIXME: Really we should apply an equal-power scaling factor here, sin ce we're effectively panning center...
275 const AudioChannel* sourceChannel = sourceBus.channel(0);
276 channel(0)->copyFrom(sourceChannel);
277 channel(1)->copyFrom(sourceChannel);
278 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) {
279 // Handle stereo -> mono case. output = 0.5 * (input.L + input.R).
280 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
281
282 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
283 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data() ;
284
285 float* destination = channelByType(ChannelLeft)->mutableData();
286 vadd(sourceL, 1, sourceR, 1, destination, 1, length());
287 float scale = 0.5;
288 vsmul(destination, 1, &scale, destination, 1, length());
289 } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) {
290 // Handle mono -> 5.1 case, copy mono channel to center.
291 channel(2)->copyFrom(sourceBus.channel(0));
292 channel(0)->zero();
293 channel(1)->zero();
294 channel(3)->zero();
295 channel(4)->zero();
296 channel(5)->zero();
297 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) {
298 // Handle 5.1 -> mono case.
299 zero();
300 speakersSumFrom5_1_ToMono(sourceBus);
301 } else {
302 // Fallback for unknown combinations.
303 discreteCopyFrom(sourceBus);
304 }
305 }
306
307 void AudioBus::speakersSumFrom(const AudioBus& sourceBus)
308 {
309 // FIXME: Implement down mixing 5.1 to stereo.
310 // https://bugs.webkit.org/show_bug.cgi?id=79192
311
312 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
313 unsigned numberOfDestinationChannels = numberOfChannels();
314
315 if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) {
316 // Handle mono -> stereo case (summing mono channel into both left and r ight).
317 const AudioChannel* sourceChannel = sourceBus.channel(0);
318 channel(0)->sumFrom(sourceChannel);
319 channel(1)->sumFrom(sourceChannel);
320 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) {
321 // Handle stereo -> mono case. output += 0.5 * (input.L + input.R).
322 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
323
324 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
325 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data() ;
326
327 float* destination = channelByType(ChannelLeft)->mutableData();
328 float scale = 0.5;
329 vsma(sourceL, 1, &scale, destination, 1, length());
330 vsma(sourceR, 1, &scale, destination, 1, length());
331 } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) {
332 // Handle mono -> 5.1 case, sum mono channel into center.
333 channel(2)->sumFrom(sourceBus.channel(0));
334 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) {
335 // Handle 5.1 -> mono case.
336 speakersSumFrom5_1_ToMono(sourceBus);
337 } else {
338 // Fallback for unknown combinations.
339 discreteSumFrom(sourceBus); 250 discreteSumFrom(sourceBus);
340 } 251 break;
341 }
342
343 void AudioBus::speakersSumFrom5_1_ToMono(const AudioBus& sourceBus)
344 {
345 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
346
347 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
348 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data();
349 const float* sourceC = sourceBusSafe.channelByType(ChannelCenter)->data();
350 const float* sourceSL = sourceBusSafe.channelByType(ChannelSurroundLeft)->da ta();
351 const float* sourceSR = sourceBusSafe.channelByType(ChannelSurroundRight)->d ata();
352
353 float* destination = channelByType(ChannelLeft)->mutableData();
354
355 AudioFloatArray temp(length());
356 float* tempData = temp.data();
357
358 // Sum in L and R.
359 vadd(sourceL, 1, sourceR, 1, tempData, 1, length());
360 float scale = 0.7071;
361 vsmul(tempData, 1, &scale, tempData, 1, length());
362 vadd(tempData, 1, destination, 1, destination, 1, length());
363
364 // Sum in SL and SR.
365 vadd(sourceSL, 1, sourceSR, 1, tempData, 1, length());
366 scale = 0.5;
367 vsmul(tempData, 1, &scale, tempData, 1, length());
368 vadd(tempData, 1, destination, 1, destination, 1, length());
369
370 // Sum in center.
371 vadd(sourceC, 1, destination, 1, destination, 1, length());
372 }
373
374 void AudioBus::discreteCopyFrom(const AudioBus& sourceBus)
375 {
376 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
377 unsigned numberOfDestinationChannels = numberOfChannels();
378
379 if (numberOfDestinationChannels < numberOfSourceChannels) {
380 // Down-mix by copying channels and dropping the remaining.
381 for (unsigned i = 0; i < numberOfDestinationChannels; ++i)
382 channel(i)->copyFrom(sourceBus.channel(i));
383 } else if (numberOfDestinationChannels > numberOfSourceChannels) {
384 // Up-mix by copying as many channels as we have, then zeroing remaining channels.
385 for (unsigned i = 0; i < numberOfSourceChannels; ++i)
386 channel(i)->copyFrom(sourceBus.channel(i));
387 for (unsigned i = numberOfSourceChannels; i < numberOfDestinationChannel s; ++i)
388 channel(i)->zero();
389 } 252 }
390 } 253 }
391 254
392 void AudioBus::discreteSumFrom(const AudioBus& sourceBus) 255 void AudioBus::discreteSumFrom(const AudioBus& sourceBus)
393 { 256 {
394 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 257 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
395 unsigned numberOfDestinationChannels = numberOfChannels(); 258 unsigned numberOfDestinationChannels = numberOfChannels();
396 259
397 if (numberOfDestinationChannels < numberOfSourceChannels) { 260 if (numberOfDestinationChannels < numberOfSourceChannels) {
398 // Down-mix by summing channels and dropping the remaining. 261 // Down-mix by summing channels and dropping the remaining.
399 for (unsigned i = 0; i < numberOfDestinationChannels; ++i) 262 for (unsigned i = 0; i < numberOfDestinationChannels; ++i)
400 channel(i)->sumFrom(sourceBus.channel(i)); 263 channel(i)->sumFrom(sourceBus.channel(i));
401 } else if (numberOfDestinationChannels > numberOfSourceChannels) { 264 } else if (numberOfDestinationChannels > numberOfSourceChannels) {
402 // Up-mix by summing as many channels as we have. 265 // Up-mix by summing as many channels as we have.
403 for (unsigned i = 0; i < numberOfSourceChannels; ++i) 266 for (unsigned i = 0; i < numberOfSourceChannels; ++i)
404 channel(i)->sumFrom(sourceBus.channel(i)); 267 channel(i)->sumFrom(sourceBus.channel(i));
405 } 268 }
406 } 269 }
407 270
271 void AudioBus::sumFromByUpMixing(const AudioBus& sourceBus)
272 {
273 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
274 unsigned numberOfDestinationChannels = numberOfChannels();
275
276 if ((numberOfSourceChannels == 1 && numberOfDestinationChannels == 2) || (nu mberOfSourceChannels == 1 && numberOfDestinationChannels == 4)) {
277 // Up-mixing: 1 -> 2, 1 -> 4
278 // output.L = input
279 // output.R = input
280 // output.SL = 0 (in the case of 1 -> 4)
281 // output.SR = 0 (in the case of 1 -> 4)
282 const AudioChannel* sourceL = sourceBus.channelByType(ChannelLeft);
283 channelByType(ChannelLeft)->sumFrom(sourceL);
284 channelByType(ChannelRight)->sumFrom(sourceL);
285 } else if (numberOfSourceChannels == 1 && numberOfDestinationChannels == 6) {
286 // Up-mixing: 1 -> 5.1
287 // output.L = 0
288 // output.R = 0
289 // output.C = input (put in center channel)
290 // output.LFE = 0
291 // output.SL = 0
292 // output.SR = 0
293 channelByType(ChannelCenter)->sumFrom(sourceBus.channelByType(ChannelLef t));
294 } else if ((numberOfSourceChannels == 2 && numberOfDestinationChannels == 4) || (numberOfSourceChannels == 2 && numberOfDestinationChannels == 6)) {
295 // Up-mixing: 2 -> 4, 2 -> 5.1
296 // output.L = input.L
297 // output.R = input.R
298 // output.C = 0 (in the case of 2 -> 5.1)
299 // output.LFE = 0 (in the case of 2 -> 5.1)
300 // output.SL = 0
301 // output.SR = 0
302 channelByType(ChannelLeft)->sumFrom(sourceBus.channelByType(ChannelLeft) );
303 channelByType(ChannelRight)->sumFrom(sourceBus.channelByType(ChannelRigh t));
304 } else if (numberOfSourceChannels == 4 && numberOfDestinationChannels == 6) {
305 // Up-mixing: 4 -> 5.1
306 // output.L = input.L
307 // output.R = input.R
308 // output.C = 0
309 // output.LFE = 0
310 // output.SL = input.SL
311 // output.SR = input.SR
312 channelByType(ChannelLeft)->sumFrom(sourceBus.channelByType(ChannelLeft) );
313 channelByType(ChannelRight)->sumFrom(sourceBus.channelByType(ChannelRigh t));
314 channelByType(ChannelSurroundLeft)->sumFrom(sourceBus.channelByType(Chan nelSurroundLeft));
315 channelByType(ChannelSurroundRight)->sumFrom(sourceBus.channelByType(Cha nnelSurroundRight));
316 } else {
317 // All other cases, fall back to the discrete sum. This will silence the
318 // excessive channels.
319 discreteSumFrom(sourceBus);
320 }
321 }
322
323 void AudioBus::sumFromByDownMixing(const AudioBus& sourceBus)
324 {
325 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
326 unsigned numberOfDestinationChannels = numberOfChannels();
327
328 if (numberOfSourceChannels == 2 && numberOfDestinationChannels == 1) {
329 // Down-mixing: 2 -> 1
330 // output = 0.5 * (input.L + input.R)
331 const float* sourceL = sourceBus.channelByType(ChannelLeft)->data();
332 const float* sourceR = sourceBus.channelByType(ChannelRight)->data();
333
334 float* destination = channelByType(ChannelLeft)->mutableData();
335 float scale = 0.5;
336
337 vsma(sourceL, 1, &scale, destination, 1, length());
338 vsma(sourceR, 1, &scale, destination, 1, length());
339 } else if (numberOfSourceChannels == 4 && numberOfDestinationChannels == 1) {
340 // Down-mixing: 4 -> 1
341 // output = 0.25 * (input.L + input.R + input.SL + input.SR)
342 const float* sourceL = sourceBus.channelByType(ChannelLeft)->data();
343 const float* sourceR = sourceBus.channelByType(ChannelRight)->data();
344 const float* sourceSL = sourceBus.channelByType(ChannelSurroundLeft)->da ta();
345 const float* sourceSR = sourceBus.channelByType(ChannelSurroundRight)->d ata();
346
347 float* destination = channelByType(ChannelLeft)->mutableData();
348 float scale = 0.25;
349
350 vsma(sourceL, 1, &scale, destination, 1, length());
351 vsma(sourceR, 1, &scale, destination, 1, length());
352 vsma(sourceSL, 1, &scale, destination, 1, length());
353 vsma(sourceSR, 1, &scale, destination, 1, length());
354 } else if (numberOfSourceChannels == 6 && numberOfDestinationChannels == 1) {
355 // Down-mixing: 5.1 -> 1
356 // output = sqrt(1/2) * (input.L + input.R) + input.C
357 // + 0.5 * (input.SL + input.SR)
358 const float* sourceL = sourceBus.channelByType(ChannelLeft)->data();
359 const float* sourceR = sourceBus.channelByType(ChannelRight)->data();
360 const float* sourceC = sourceBus.channelByType(ChannelCenter)->data();
361 const float* sourceSL = sourceBus.channelByType(ChannelSurroundLeft)->da ta();
362 const float* sourceSR = sourceBus.channelByType(ChannelSurroundRight)->d ata();
363
364 float* destination = channelByType(ChannelLeft)->mutableData();
365 float scaleSqrtHalf = sqrtf(0.5);
366 float scaleHalf = 0.5;
367
368 vsma(sourceL, 1, &scaleSqrtHalf, destination, 1, length());
369 vsma(sourceR, 1, &scaleSqrtHalf, destination, 1, length());
370 vadd(sourceC, 1, destination, 1, destination, 1, length());
371 vsma(sourceSL, 1, &scaleHalf, destination, 1, length());
372 vsma(sourceSR, 1, &scaleHalf, destination, 1, length());
373 } else if (numberOfSourceChannels == 4 && numberOfDestinationChannels == 2) {
374 // Down-mixing: 4 -> 2
375 // output.L = 0.5 * (input.L + input.SL)
376 // output.R = 0.5 * (input.R + input.SR)
377 const float* sourceL = sourceBus.channelByType(ChannelLeft)->data();
378 const float* sourceR = sourceBus.channelByType(ChannelRight)->data();
379 const float* sourceSL = sourceBus.channelByType(ChannelSurroundLeft)->da ta();
380 const float* sourceSR = sourceBus.channelByType(ChannelSurroundRight)->d ata();
381
382 float* destinationL = channelByType(ChannelLeft)->mutableData();
383 float* destinationR = channelByType(ChannelRight)->mutableData();
384 float scaleHalf = 0.5;
385
386 vsma(sourceL, 1, &scaleHalf, destinationL, 1, length());
387 vsma(sourceSL, 1, &scaleHalf, destinationL, 1, length());
388 vsma(sourceR, 1, &scaleHalf, destinationR, 1, length());
389 vsma(sourceSR, 1, &scaleHalf, destinationR, 1, length());
390 } else if (numberOfSourceChannels == 6 && numberOfDestinationChannels == 2) {
391 // Down-mixing: 5.1 -> 2
392 // output.L = input.L + sqrt(1/2) * (input.C + input.SL)
393 // output.R = input.R + sqrt(1/2) * (input.C + input.SR)
394 const float* sourceL = sourceBus.channelByType(ChannelLeft)->data();
395 const float* sourceR = sourceBus.channelByType(ChannelRight)->data();
396 const float* sourceC = sourceBus.channelByType(ChannelCenter)->data();
397 const float* sourceSL = sourceBus.channelByType(ChannelSurroundLeft)->da ta();
398 const float* sourceSR = sourceBus.channelByType(ChannelSurroundRight)->d ata();
399
400 float* destinationL = channelByType(ChannelLeft)->mutableData();
401 float* destinationR = channelByType(ChannelRight)->mutableData();
402 float scaleSqrtHalf = sqrtf(0.5);
403
404 vadd(sourceL, 1, destinationL, 1, destinationL, 1, length());
405 vsma(sourceC, 1, &scaleSqrtHalf, destinationL, 1, length());
406 vsma(sourceSL, 1, &scaleSqrtHalf, destinationL, 1, length());
407 vadd(sourceR, 1, destinationR, 1, destinationR, 1, length());
408 vsma(sourceC, 1, &scaleSqrtHalf, destinationR, 1, length());
409 vsma(sourceSR, 1, &scaleSqrtHalf, destinationR, 1, length());
410 } else if (numberOfSourceChannels == 6 && numberOfDestinationChannels == 4) {
411 // Down-mixing: 5.1 -> 4
412 // output.L = input.L + sqrt(1/2) * input.C
413 // output.R = input.R + sqrt(1/2) * input.C
414 // output.SL = input.SL
415 // output.SR = input.SR
416 const float* sourceL = sourceBus.channelByType(ChannelLeft)->data();
417 const float* sourceR = sourceBus.channelByType(ChannelRight)->data();
418 const float* sourceC = sourceBus.channelByType(ChannelCenter)->data();
419
420 float* destinationL = channelByType(ChannelLeft)->mutableData();
421 float* destinationR = channelByType(ChannelRight)->mutableData();
422 float scaleSqrtHalf = sqrtf(0.5);
423
424 vadd(sourceL, 1, destinationL, 1, destinationL, 1, length());
425 vsma(sourceC, 1, &scaleSqrtHalf, destinationL, 1, length());
426 vadd(sourceR, 1, destinationR, 1, destinationR, 1, length());
427 vsma(sourceC, 1, &scaleSqrtHalf, destinationR, 1, length());
428 channel(2)->sumFrom(sourceBus.channel(4));
429 channel(3)->sumFrom(sourceBus.channel(5));
430 } else {
431 // All other cases, fall back to the discrete sum. This will perform
432 // channel-wise sum until the destination channels run out.
433 discreteSumFrom(sourceBus);
434 }
435 }
436
408 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, f loat targetGain) 437 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, f loat targetGain)
409 { 438 {
410 if (!topologyMatches(sourceBus)) { 439 if (!topologyMatches(sourceBus)) {
411 ASSERT_NOT_REACHED(); 440 ASSERT_NOT_REACHED();
412 zero(); 441 zero();
413 return; 442 return;
414 } 443 }
415 444
416 if (sourceBus.isSilent()) { 445 if (sourceBus.isSilent()) {
417 zero(); 446 zero();
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 705
677 // If the bus needs no conversion then return as is. 706 // If the bus needs no conversion then return as is.
678 if ((!mixToMono || audioBus->numberOfChannels() == 1) && audioBus->sampleRat e() == sampleRate) 707 if ((!mixToMono || audioBus->numberOfChannels() == 1) && audioBus->sampleRat e() == sampleRate)
679 return audioBus; 708 return audioBus;
680 709
681 return AudioBus::createBySampleRateConverting(audioBus.get(), mixToMono, sam pleRate); 710 return AudioBus::createBySampleRateConverting(audioBus.get(), mixToMono, sam pleRate);
682 } 711 }
683 712
684 } // namespace blink 713 } // namespace blink
685 714
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/audio/AudioBus.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698