Not interested in silverlight. Flash/javascript/html5 solutions are acceptable.
If you do not know such solutions, could you please say is it possible to make such that
A simple Google search led me to these sites:
Aurora and FLAC.js — audio codecs using the Web Audio API
Introducing FLAC.js: A Pure JavaScript FLAC Decoder
Believe it or not, it wasn't so hard.
Almost forgot:
Check HTML5Test to compare browsers performance/compatibility with the <audio>
tag and it's siblings.
When I had to play FLAC in-browser, my starting point was also the Aurora framework.
However, the Aurora player is geared around using ScriptProcessorNode to decode chunks of audio on the fly. This didn't pan out for many reasons.
My solution was to decode the Flac to raw 16bit PCM audio, using a stripped down Aurora.js Assset class + dependencies.
Look in the source for Asset.get( 'format', callback ), Asset.fromFile, and Asset.prototype.decodeToBuffer.
Next, take the audio data, along with extracted values for sample-rate and channel count, and build a WAVE file. This can be played using an HTML5 audio element, sent though an audio graph using createMediaElementSource, or absolutely anything you can do with natively supported audio formats.
Note: Replace clz function in decoder.js with the native Math.clz32 to boost performance, and polyfill clz32 for old browsers.
Disadvantage
The decoding time. Around 5 seconds at ~100% CPU for an "average" 4min song.
Advantages
Here's the function to build the WAVE header, and turn the raw PCM data into something the browser can natively play.
function createWave( audioData, sampleRate, channelCount )
{
const audioFormat = 1, // 2 PCM = 1
subChunk1Size= 16, // 4 PCM = 16
bitsPerSample= 16, // 2
blockAlign = channelCount * (bitsPerSample >> 3), // 2
byteRate = blockAlign * sampleRate, // 4
subChunk2Size= blockAlign * audioData.size, // 4
chunkSize = 36 + subChunk2Size, // 4
// Total header size 44 bytes
header = new DataView( new ArrayBuffer(44) );
header.setUint32( 0, 0x52494646 ); // chunkId=RIFF
header.setUint32( 4, chunkSize, true );
header.setUint32( 8, 0x57415645 ); // format=WAVE
header.setUint32( 12, 0x666d7420 ); // subChunk1Id=fmt
header.setUint32( 16, subChunk1Size, true );
header.setUint16( 20, audioFormat, true );
header.setUint16( 22, channelCount, true );
header.setUint32( 24, sampleRate, true );
header.setUint32( 28, byteRate, true );
header.setUint16( 32, blockAlign, true );
header.setUint16( 34, bitsPerSample, true );
header.setUint32( 36, 0x64617461 ); // subChunk2Id=data
header.setUint32( 40, subChunk2Size, true );
return URL.createObjectURL( new Blob( [header, audioData], {type: 'audio/wav'} ) );
}