int flac_enc_init_FILE(flac_enc *flac, FILE *fout) { FLAC__StreamEncoderInitStatus init_status; init_status = FLAC__stream_encoder_init_FILE(flac->encoder, fout, progress_callback, /*client_data=*/NULL); if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { fprintf(stderr, _("ERROR: initializing encoder: %s\n"), FLAC__StreamEncoderInitStatusString[init_status]); return 1; } return 0; }
static FLAC__StreamDecoderWriteStatus write_cb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) { FLACClientData &client = *static_cast<FLACClientData *>(client_data); if(!client.started) { client.started = true; client.delaySamples = static_cast<uint32_t>(0.5 + (delay * sampleRate) / 1000.0); for(auto m = client.metadata.begin(); m != client.metadata.end(); m++) { auto metadata = *m; if(metadata->type == FLAC__METADATA_TYPE_APPLICATION && !memcmp(metadata->data.application.id, "riff", 4)) { if(metadata->length > 8 + sizeof(WAVSampleInfoChunk) && !memcmp(metadata->data.application.data, "smpl", 4)) { WAVSampleInfoChunk *smpl = reinterpret_cast<WAVSampleInfoChunk *>(metadata->data.application.data + 8); for(uint32_t i = 0; i < smpl->numLoops; i++) { WAVSampleLoop *loop = reinterpret_cast<WAVSampleLoop *>(smpl + 1) + i; if(loop->loopStart >= client.delaySamples) loop->loopStart -= client.delaySamples; if(loop->loopEnd >= client.delaySamples) loop->loopEnd -= client.delaySamples; } } } } if(!FLAC__stream_encoder_set_metadata(client.encoder, client.metadata.data(), client.metadata.size())) { std::cerr << "Cannot set FLAC metadata!" << std::endl; client.started = false; return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } if(FLAC__stream_encoder_init_FILE(client.encoder, client.of, nullptr, nullptr) != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { std::cerr << "Cannot init FLAC encoder!" << std::endl; client.started = false; return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } } if(client.delaySamples >= frame->header.blocksize) { client.delaySamples -= frame->header.blocksize; } else if(client.delaySamples > 0) { std::vector<const FLAC__int32 *> newBuffer(client.channels); for(uint32_t chn = 0; chn < client.channels; chn++) { newBuffer[chn] = buffer[chn] + client.delaySamples; } FLAC__stream_encoder_process(client.encoder, newBuffer.data(), frame->header.blocksize - client.delaySamples); client.delaySamples = 0; } else { FLAC__stream_encoder_process(client.encoder, buffer, frame->header.blocksize); } return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; }
int __stdcall WWFlacRW_EncodeRun(int id, const wchar_t *path) { FILE *fp = NULL; errno_t ercd; int64_t left; int64_t readPos; int64_t writePos; FLAC__bool ok = true; FLAC__int32 *pcm = NULL; if (NULL == path || wcslen(path) == 0) { return FRT_BadParams; } FLAC__StreamEncoderInitStatus initStatus = FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; FlacEncodeInfo *fei = FlacTInfoFindById<FlacEncodeInfo>(g_flacEncodeInfoMap, id); if (NULL == fei) { return FRT_IdNotFound; } if (0 < fei->pictureBytes && fei->pictureData == NULL) { dprintf("%s picture data is not set yet.\n", __FUNCTION__); return FRT_DataNotReady; } assert(fei->buffPerChannel); ok = FLAC__stream_encoder_set_metadata(fei->encoder, &fei->flacMetaArray[0], fei->flacMetaCount); if(!ok) { dprintf("FLAC__stream_encoder_set_metadata failed\n"); fei->errorCode = FRT_OtherError; goto end; } for (int ch=0; ch<fei->channels; ++ch) { if (fei->buffPerChannel[ch] == NULL){ dprintf("%s pcm buffer is not set yet.\n", __FUNCTION__); return FRT_DataNotReady; } } if (fei->bitsPerSample != 16 && fei->bitsPerSample != 24) { return FRT_InvalidBitsPerSample; } pcm = new FLAC__int32[FLACENCODE_READFRAMES * fei->channels]; if (pcm == NULL) { return FRT_MemoryExhausted; } // Windowsでは、この方法でファイルを開かなければならぬ。 wcsncpy_s(fei->path, path, (sizeof fei->path)/2-1); ercd = _wfopen_s(&fp, fei->path, L"wb"); if (ercd != 0 || NULL == fp) { fei->errorCode = FRT_FileOpenError; goto end; } initStatus = FLAC__stream_encoder_init_FILE(fei->encoder, fp, ProgressCallback, fei); if(initStatus != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { dprintf("FLAC__stream_encoder_init_FILE failed %s\n", FLAC__StreamEncoderInitStatusString[initStatus]); switch (initStatus) { case FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR: { FLAC__StreamDecoderState state = FLAC__stream_encoder_get_verify_decoder_state(fei->encoder); dprintf("decoderState=%d\n", state); } fei->errorCode = FRT_EncoderError; goto end; case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS: fei->errorCode = FRT_InvalidNumberOfChannels; goto end; case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE: fei->errorCode = FRT_InvalidBitsPerSample; goto end; case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE: fei->errorCode = FRT_InvalidSampleRate; goto end; case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA: fei->errorCode = FRT_InvalidMetadata; goto end; case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS: case FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED: case FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER: case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE: case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER: case FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION: case FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER: case FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE: default: fei->errorCode = FRT_OtherError; goto end; } } fp = NULL; readPos = 0; left = fei->totalSamples; while(ok && left) { uint32_t need = left>FLACENCODE_READFRAMES ? FLACENCODE_READFRAMES : (unsigned int)left; // create interleaved PCM samples to pcm[] writePos = 0; switch (fei->bitsPerSample) { case 16: for (uint32_t i=0; i<need; ++i) { for (int ch=0; ch<fei->channels;++ch) { uint8_t *p = &fei->buffPerChannel[ch][readPos]; int v = (p[0]<<16) + (p[1]<<24); pcm[writePos] = v>>16; ++writePos; } readPos += 2; } break; case 24: for (uint32_t i=0; i<need; ++i) { for (int ch=0; ch<fei->channels;++ch) { uint8_t *p = &fei->buffPerChannel[ch][readPos]; int v = (p[0]<<8) + (p[1]<<16) + (p[2]<<24); pcm[writePos] = v >> 8; ++writePos; } readPos += 3; } break; default: assert(0); break; } ok = FLAC__stream_encoder_process_interleaved(fei->encoder, pcm, need); left -= need; } if (!ok) { dprintf("FLAC__stream_encoder_process_interleaved failed"); fei->errorCode = FRT_EncoderProcessFailed; } end: delete [] pcm; pcm = NULL; if (NULL != fp) { fclose(fp); fp = NULL; } if (NULL != fei->encoder) { if (initStatus == FLAC__STREAM_ENCODER_INIT_STATUS_OK) { FLAC__stream_encoder_finish(fei->encoder); } DeleteFlacMetaArray(fei); FLAC__stream_encoder_delete(fei->encoder); fei->encoder = NULL; } if (fei->errorCode < 0) { int result = fei->errorCode; FlacTInfoDelete<FlacEncodeInfo>(g_flacEncodeInfoMap, fei); fei = NULL; return result; } return fei->id; }