Esempio n. 1
0
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;
}
Esempio n. 3
0
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;
}