├── Debug ├── libhackrf.dll ├── libhackrf.exp ├── libhackrf.ilk ├── libhackrf.lib ├── libhackrf.pdb ├── pthreadGC2.dll ├── pthreadGCE2.dll ├── pthreadVC2.dll ├── pthreadVCE2.dll └── pthreadVSE2.dll ├── HackRF_Transmitter.v12.suo ├── README.md ├── HackRF_Transmitter ├── HackRF_Transmitter.vcxproj.user ├── IHackRFData.h ├── WavSource.cpp ├── HackRFDevice.h ├── WavSource.h ├── FMModulator.h ├── HackRFDevice.cpp ├── main.cpp ├── HackRF_Transmitter.vcxproj.filters ├── input.h ├── write_wav.h ├── FMModulator.cpp ├── HackRF_Transmitter.vcxproj ├── write_wav.cpp ├── hackrf.h └── input.cpp └── HackRF_Transmitter.sln /Debug/libhackrf.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/libhackrf.dll -------------------------------------------------------------------------------- /Debug/libhackrf.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/libhackrf.exp -------------------------------------------------------------------------------- /Debug/libhackrf.ilk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/libhackrf.ilk -------------------------------------------------------------------------------- /Debug/libhackrf.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/libhackrf.lib -------------------------------------------------------------------------------- /Debug/libhackrf.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/libhackrf.pdb -------------------------------------------------------------------------------- /Debug/pthreadGC2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/pthreadGC2.dll -------------------------------------------------------------------------------- /Debug/pthreadGCE2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/pthreadGCE2.dll -------------------------------------------------------------------------------- /Debug/pthreadVC2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/pthreadVC2.dll -------------------------------------------------------------------------------- /Debug/pthreadVCE2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/pthreadVCE2.dll -------------------------------------------------------------------------------- /Debug/pthreadVSE2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/Debug/pthreadVSE2.dll -------------------------------------------------------------------------------- /HackRF_Transmitter.v12.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gsj0791/HackRF_FM_Transmitter/HEAD/HackRF_Transmitter.v12.suo -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HackRF_FM_Transmitter 2 | HackRF FM Transmitter On Windows 3 | This Code base On https://github.com/jocover/foo_hackrf 4 | -------------------------------------------------------------------------------- /HackRF_Transmitter/HackRF_Transmitter.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /HackRF_Transmitter/IHackRFData.h: -------------------------------------------------------------------------------- 1 | #ifndef _IHACKRFDATA_H 2 | #define _IHACKRFDATA_H 3 | 4 | #include 5 | 6 | class IHackRFData 7 | { 8 | public: 9 | IHackRFData() {}; 10 | ~IHackRFData() {}; 11 | 12 | virtual int onData(int8_t* buffer, uint32_t length) = 0; 13 | }; 14 | 15 | #endif // !_IHACKRFDATA_H 16 | -------------------------------------------------------------------------------- /HackRF_Transmitter/WavSource.cpp: -------------------------------------------------------------------------------- 1 | #include "WavSource.h" 2 | 3 | #define DEBUG 1 4 | 5 | WavSource::WavSource(const char *filename, int inputSamples) 6 | :_inputSamples(inputSamples) 7 | { 8 | pcmHeader = wav_open_read(filename, 0); 9 | audioDataPos = ftell(pcmHeader->f); 10 | _buf = (float *)malloc(inputSamples*sizeof(float)* pcmHeader->channels); 11 | } 12 | 13 | 14 | WavSource::~WavSource() 15 | { 16 | free(_buf); 17 | wav_close(pcmHeader); 18 | } 19 | 20 | int WavSource::readData(){ 21 | return wav_read_float32(pcmHeader, _buf, _inputSamples * pcmHeader->channels, NULL); 22 | } 23 | 24 | void WavSource::reset(){ 25 | fseek(pcmHeader->f, audioDataPos, SEEK_SET); 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /HackRF_Transmitter/HackRFDevice.h: -------------------------------------------------------------------------------- 1 | #ifndef _HACKRFDEIVCE_H 2 | #define _HACKRFDEIVCE_H 3 | #include "IHackRFData.h" 4 | #include "hackrf.h" 5 | #include 6 | #include 7 | 8 | class HackRFDevice 9 | { 10 | private: 11 | hackrf_device *_dev; 12 | IHackRFData *mHandler; 13 | bool running; 14 | uint32_t hackrf_sample = 2000000; 15 | 16 | public: 17 | HackRFDevice(); 18 | ~HackRFDevice(); 19 | 20 | int HackRFCallback(int8_t* buffer, uint32_t length); 21 | 22 | bool Open(IHackRFData *handler); 23 | void SetFrequency(uint64_t freg); 24 | void SetGain(float gain); 25 | void SetAMP(bool enableamp); 26 | void SetSampleRate(uint32_t sample_rate); 27 | bool StartTx(); 28 | void Close(); 29 | }; 30 | 31 | #endif // ! 32 | -------------------------------------------------------------------------------- /HackRF_Transmitter/WavSource.h: -------------------------------------------------------------------------------- 1 | #ifndef _WAVSOURCE_H 2 | #define _WAVSOURCE_H 3 | 4 | #include "input.h" 5 | 6 | class WavSource 7 | { 8 | private: 9 | pcmfile_t *pcmHeader; 10 | float *_buf; 11 | int _inputSamples; 12 | int audioDataPos = 0; 13 | 14 | public: 15 | WavSource(const char *filename, int inputSamples); 16 | ~WavSource(); 17 | 18 | int readData(); 19 | int getChannels(){ return pcmHeader->channels; }; 20 | int getSampleRate(){ return pcmHeader->samplerate; } 21 | int getSampleByte(){ return pcmHeader->samplebytes; } 22 | int getSamples(){ return pcmHeader->samples; } 23 | int getSampleCount(){ return _inputSamples; } 24 | float *getData() { return _buf; }; 25 | void reset(); 26 | }; 27 | 28 | #endif // !_WAVSOURCE_H 29 | 30 | -------------------------------------------------------------------------------- /HackRF_Transmitter/FMModulator.h: -------------------------------------------------------------------------------- 1 | #ifndef _FMMODULATOR_H 2 | #define _FMMODULATOR_H 3 | 4 | #include 5 | #include "IHackRFData.h" 6 | #include "WavSource.h" 7 | 8 | 9 | #define BUF_LEN 262144 //hackrf tx buf 10 | 11 | class FMModulator:public IHackRFData 12 | { 13 | private: 14 | std::mutex m_mutex; 15 | int count; 16 | int8_t ** _buf_ptr; 17 | bool inited; 18 | int tail; 19 | int head; 20 | float gain; 21 | uint32_t mode; 22 | float * audio_buf; 23 | float * new_audio_buf; 24 | float * IQ_buf; 25 | uint32_t m_sample_rate; 26 | size_t m_sample_count; 27 | uint32_t hackrf_sample; 28 | double fm_phase; 29 | double fm_deviation; 30 | float last_in_samples[4]; 31 | 32 | private: 33 | void interpolation(float * in_buf, uint32_t in_samples, float * out_buf, uint32_t out_samples, float last_in_samples[4]); 34 | void modulation(float * input, float * output, uint32_t mode); 35 | void work(float *input_items, uint32_t len); 36 | 37 | public: 38 | FMModulator(float _gain, uint32_t _mode, uint32_t _sample); 39 | ~FMModulator(); 40 | 41 | int onData(int8_t* buffer, uint32_t length); 42 | void Start(WavSource *source); 43 | }; 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /HackRF_Transmitter/HackRFDevice.cpp: -------------------------------------------------------------------------------- 1 | #include "HackRFDevice.h" 2 | 3 | 4 | int _hackrf_tx_callback(hackrf_transfer *transfer) { 5 | HackRFDevice *obj = (HackRFDevice *)transfer->tx_ctx; 6 | return obj->HackRFCallback((int8_t *)transfer->buffer, transfer->valid_length); 7 | } 8 | 9 | HackRFDevice::HackRFDevice() 10 | :_dev(NULL), running(false) 11 | { 12 | } 13 | 14 | 15 | HackRFDevice::~HackRFDevice() 16 | { 17 | if (_dev) { 18 | this->Close(); 19 | } 20 | } 21 | 22 | bool HackRFDevice::Open(IHackRFData *handler){ 23 | mHandler = handler; 24 | hackrf_init(); 25 | 26 | int ret = hackrf_open(&_dev); 27 | if (ret != HACKRF_SUCCESS) { 28 | printf("Failed to open HackRF device"); 29 | hackrf_close(_dev); 30 | return false; 31 | } 32 | return true; 33 | } 34 | 35 | int HackRFDevice::HackRFCallback(int8_t* buffer, uint32_t length) 36 | { 37 | return mHandler->onData(buffer, length); 38 | } 39 | 40 | bool HackRFDevice::StartTx() 41 | { 42 | running = true; 43 | int ret = hackrf_start_tx(_dev, _hackrf_tx_callback, (void *)this); 44 | if (ret != HACKRF_SUCCESS) { 45 | printf("Failed to start TX streaming"); 46 | hackrf_close(_dev); 47 | running = false; 48 | } 49 | 50 | return running; 51 | } 52 | 53 | void HackRFDevice::SetFrequency(uint64_t freg) 54 | { 55 | hackrf_set_freq(_dev, freg); 56 | } 57 | 58 | void HackRFDevice::SetGain(float gain) 59 | { 60 | hackrf_set_txvga_gain(_dev, gain); 61 | } 62 | 63 | void HackRFDevice::SetAMP(bool enableamp) 64 | { 65 | hackrf_set_amp_enable(_dev, enableamp); 66 | } 67 | 68 | void HackRFDevice::SetSampleRate(uint32_t sample_rate) 69 | { 70 | hackrf_set_sample_rate(_dev, sample_rate); 71 | hackrf_set_baseband_filter_bandwidth(_dev, 1750000); 72 | } 73 | 74 | void HackRFDevice::Close() { 75 | running = false; 76 | hackrf_stop_tx(_dev); 77 | hackrf_close(_dev); 78 | _dev = NULL; 79 | } 80 | -------------------------------------------------------------------------------- /HackRF_Transmitter/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "WavSource.h" 3 | #include "FMModulator.h" 4 | #include "HackRFDevice.h" 5 | #include "write_wav.h" 6 | 7 | #define HACKRF_SAMPLE 2000000 8 | #define SAMPLE_COUNT 2048 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | WavSource *wav = new WavSource("f:\\notouch.wav", SAMPLE_COUNT); 13 | 14 | uint32_t avSamplesPerSecByte = wav->getSampleByte() * wav->getChannels() * wav->getSampleRate(); 15 | //176400 16 | int PerTimeStamp = 1000 / (avSamplesPerSecByte / (SAMPLE_COUNT * wav->getChannels())); 17 | int readTotalAudioByte = 0; 18 | int PerSamplesPerSecByte = SAMPLE_COUNT * wav->getSampleByte(); 19 | int m_read_buf_size; 20 | int nTimeStamp = 0; 21 | int fTimeStamp = 0; 22 | double audioTimeTick = GetTickCount(); 23 | 24 | int sample_rate = wav->getSampleRate()*1.0 / SAMPLE_COUNT*BUF_LEN; 25 | 26 | FMModulator *mod = new FMModulator(90, 0, sample_rate); 27 | HackRFDevice *device = new HackRFDevice(); 28 | 29 | if (!device->Open(mod)) { 30 | return 0; 31 | } 32 | 33 | device->SetSampleRate(sample_rate); 34 | device->SetFrequency(2600000000); 35 | device->SetGain(40); 36 | device->SetAMP(0); 37 | device->StartTx(); 38 | 39 | //WAV_Writer wavFile; 40 | //Audio_WAV_OpenWriter(&wavFile, "f:\\test11111111111.wav", wav->getSampleRate(), wav->getSampleByte()); 41 | 42 | while (1) 43 | { 44 | nTimeStamp = GetTickCount() - audioTimeTick; 45 | fTimeStamp = ((readTotalAudioByte + SAMPLE_COUNT)*2 / PerSamplesPerSecByte) * PerTimeStamp; 46 | 47 | if (nTimeStamp > fTimeStamp){ 48 | m_read_buf_size = wav->readData(); 49 | //fwrite(wav->getData(), wav->getChannels(), SAMPLE_COUNT * sizeof(float), wavFile.fid); 50 | //wavFile.dataSize += wav->getChannels()* SAMPLE_COUNT * sizeof(float); 51 | 52 | mod->Start(wav); 53 | readTotalAudioByte += m_read_buf_size; 54 | if (!m_read_buf_size){ 55 | audioTimeTick = GetTickCount(); 56 | readTotalAudioByte = 0; 57 | wav->reset(); 58 | } 59 | } 60 | Sleep(5); 61 | } 62 | 63 | //Audio_WAV_CloseWriter(&wavFile); 64 | device->Close(); 65 | delete(mod); 66 | return 0; 67 | } -------------------------------------------------------------------------------- /HackRF_Transmitter/HackRF_Transmitter.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | -------------------------------------------------------------------------------- /HackRF_Transmitter/input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FAAC - Freeware Advanced Audio Coder 3 | * Copyright (C) 2002 Krzysztof Nikiel 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * $Id: input.h,v 1.7 2008/11/24 22:00:11 menno Exp $ 20 | */ 21 | 22 | #ifndef _INPUT_H 23 | #define _INPUT_H 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include 30 | #include 31 | #ifdef HAVE_SYS_TYPES_H 32 | # include 33 | #endif 34 | #ifndef __MPEG4IP_INCLUDED__ 35 | /* Let's avoid some boring conflicting declarations */ 36 | #ifdef HAVE_INTTYPES_H 37 | # include 38 | #endif 39 | #ifdef HAVE_STDINT_H 40 | # include 41 | #endif 42 | 43 | #ifndef HAVE_INT32_T 44 | typedef signed int int32_t; 45 | #endif 46 | #ifndef HAVE_INT16_T 47 | typedef signed short int16_t; 48 | #endif 49 | #ifndef HAVE_U_INT32_T 50 | typedef unsigned int u_int32_t; 51 | #endif 52 | #ifndef HAVE_U_INT16_T 53 | typedef unsigned short u_int16_t; 54 | #endif 55 | #endif /* #ifndef __MPEG4IP_INCLUDED__ */ 56 | 57 | 58 | typedef struct 59 | { 60 | FILE *f; 61 | int channels; 62 | int samplebytes; 63 | int samplerate; 64 | int samples; 65 | int bigendian; 66 | int isfloat; 67 | } pcmfile_t; 68 | 69 | pcmfile_t *wav_open_read(const char *path, int rawchans); 70 | size_t wav_read_float32(pcmfile_t *sndf, float *buf, size_t num, int *map); 71 | size_t wav_read_int24(pcmfile_t *sndf, int32_t *buf, size_t num, int *map); 72 | size_t wav_read_int24_buf(pcmfile_t *sndf, int32_t *outbuf, size_t num, unsigned char *inputbuf); 73 | int wav_close(pcmfile_t *file); 74 | 75 | #endif /* _INPUT_H */ 76 | -------------------------------------------------------------------------------- /HackRF_Transmitter.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HackRF_Transmitter", "HackRF_Transmitter\HackRF_Transmitter.vcxproj", "{BD76BC64-68F9-470F-A778-593BC958D301}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhackrf", "..\libhackrf\libhackrf\libhackrf.vcxproj", "{27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Mixed Platforms = Debug|Mixed Platforms 13 | Debug|Win32 = Debug|Win32 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Mixed Platforms = Release|Mixed Platforms 17 | Release|Win32 = Release|Win32 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 23 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|Mixed Platforms.Build.0 = Debug|Win32 24 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|Win32.Build.0 = Debug|Win32 26 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|x64.ActiveCfg = Debug|x64 27 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|x64.Build.0 = Debug|x64 28 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|x86.ActiveCfg = Debug|Win32 29 | {BD76BC64-68F9-470F-A778-593BC958D301}.Debug|x86.Build.0 = Debug|Win32 30 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|Mixed Platforms.ActiveCfg = Release|Win32 31 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|Mixed Platforms.Build.0 = Release|Win32 32 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|Win32.ActiveCfg = Release|Win32 33 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|Win32.Build.0 = Release|Win32 34 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|x64.ActiveCfg = Release|x64 35 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|x64.Build.0 = Release|x64 36 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|x86.ActiveCfg = Release|Win32 37 | {BD76BC64-68F9-470F-A778-593BC958D301}.Release|x86.Build.0 = Release|Win32 38 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 39 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|Mixed Platforms.Build.0 = Debug|Win32 40 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|Win32.ActiveCfg = Debug|Win32 41 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|Win32.Build.0 = Debug|Win32 42 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|x64.ActiveCfg = Debug|x64 43 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|x64.Build.0 = Debug|x64 44 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|x86.ActiveCfg = Debug|Win32 45 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Debug|x86.Build.0 = Debug|Win32 46 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|Mixed Platforms.ActiveCfg = Release|Win32 47 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|Mixed Platforms.Build.0 = Release|Win32 48 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|Win32.ActiveCfg = Release|Win32 49 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|Win32.Build.0 = Release|Win32 50 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|x64.ActiveCfg = Release|x64 51 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|x64.Build.0 = Release|x64 52 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|x86.ActiveCfg = Release|Win32 53 | {27A2D86B-5C35-49ED-AC77-C9F515C9F0E9}.Release|x86.Build.0 = Release|Win32 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /HackRF_Transmitter/write_wav.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PortAudio Portable Real-Time Audio Library 3 | * Latest Version at: http://www.portaudio.com 4 | * 5 | * Copyright (c) 1999-2010 Phil Burk and Ross Bencina 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, 11 | * publish, distribute, sublicense, and/or sell copies of the Software, 12 | * and to permit persons to whom the Software is furnished to do so, 13 | * subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 22 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 23 | * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * The text above constitutes the entire PortAudio license; however, 29 | * the PortAudio community also makes the following non-binding requests: 30 | * 31 | * Any person wishing to distribute modifications to the Software is 32 | * requested to send the modifications to the original developer so that 33 | * they can be incorporated into the canonical version. It is also 34 | * requested that these non-binding requests be included along with the 35 | * license above. 36 | */ 37 | #ifndef _WAV_WRITER_H 38 | #define _WAV_WRITER_H 39 | 40 | /* 41 | * WAV file writer. 42 | * 43 | * Author: Phil Burk 44 | */ 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | /* Define WAV Chunk and FORM types as 4 byte integers. */ 51 | #define RIFF_ID (('R'<<24) | ('I'<<16) | ('F'<<8) | 'F') 52 | #define WAVE_ID (('W'<<24) | ('A'<<16) | ('V'<<8) | 'E') 53 | #define FMT_ID (('f'<<24) | ('m'<<16) | ('t'<<8) | ' ') 54 | #define DATA_ID (('d'<<24) | ('a'<<16) | ('t'<<8) | 'a') 55 | #define FACT_ID (('f'<<24) | ('a'<<16) | ('c'<<8) | 't') 56 | 57 | /* Errors returned by Audio_ParseSampleImage_WAV */ 58 | #define WAV_ERR_CHUNK_SIZE (-1) /* Chunk size is illegal or past file size. */ 59 | #define WAV_ERR_FILE_TYPE (-2) /* Not a WAV file. */ 60 | #define WAV_ERR_ILLEGAL_VALUE (-3) /* Illegal or unsupported value. Eg. 927 bits/sample */ 61 | #define WAV_ERR_FORMAT_TYPE (-4) /* Unsupported format, eg. compressed. */ 62 | #define WAV_ERR_TRUNCATED (-5) /* End of file missing. */ 63 | 64 | /* WAV PCM data format ID */ 65 | #define WAVE_FORMAT_PCM (0x0001) 66 | #define WAVE_FORMAT_IEEE_FLOAT (0x0003) 67 | #define WAVE_FORMAT_IMA_ADPCM (0x0011) 68 | 69 | 70 | typedef struct WAV_Writer_s 71 | { 72 | FILE *fid; 73 | /* Offset in file for data size. */ 74 | int dataSizeOffset; 75 | int dataSize; 76 | } WAV_Writer; 77 | 78 | /********************************************************************************* 79 | * Open named file and write WAV header to the file. 80 | * The header includes the DATA chunk type and size. 81 | * Returns number of bytes written to file or negative error code. 82 | */ 83 | long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame ); 84 | 85 | /********************************************************************************* 86 | * Write to the data chunk portion of a WAV file. 87 | * Returns bytes written or negative error code. 88 | */ 89 | long Audio_WAV_WriteShorts( WAV_Writer *writer, 90 | short *samples, 91 | int numSamples 92 | ); 93 | 94 | /********************************************************************************* 95 | * Close WAV file. 96 | * Update chunk sizes so it can be read by audio applications. 97 | */ 98 | long Audio_WAV_CloseWriter( WAV_Writer *writer ); 99 | 100 | #ifdef __cplusplus 101 | }; 102 | #endif 103 | 104 | #endif /* _WAV_WRITER_H */ 105 | -------------------------------------------------------------------------------- /HackRF_Transmitter/FMModulator.cpp: -------------------------------------------------------------------------------- 1 | #include "FMModulator.h" 2 | 3 | 4 | #define BUF_NUM 256 5 | #define BYTES_PER_SAMPLE 2 6 | #define M_PI 3.14159265358979323846 7 | 8 | 9 | FMModulator::FMModulator(float _gain, uint32_t _mode, uint32_t _sample) 10 | :gain(_gain / (float)100.0), mode(_mode), inited(false), hackrf_sample(_sample) 11 | { 12 | audio_buf = NULL; 13 | new_audio_buf = NULL; 14 | IQ_buf = NULL; 15 | memset(last_in_samples, 0, sizeof(last_in_samples)); 16 | 17 | count = tail = head = 0; 18 | 19 | _buf_ptr = (int8_t **)malloc(BUF_NUM * sizeof(int8_t *)); 20 | if (_buf_ptr) { 21 | for (unsigned int i = 0; i < BUF_NUM; ++i) { 22 | _buf_ptr[i] = (int8_t *)malloc(BUF_LEN*sizeof(int8_t)); 23 | } 24 | } 25 | } 26 | 27 | 28 | FMModulator::~FMModulator() 29 | { 30 | if (_buf_ptr) { 31 | for (unsigned int i = 0; i < BUF_NUM; ++i) { 32 | if (_buf_ptr[i]) 33 | free(_buf_ptr[i]); 34 | } 35 | free(_buf_ptr); 36 | } 37 | 38 | delete IQ_buf; 39 | delete new_audio_buf; 40 | delete audio_buf; 41 | } 42 | 43 | void FMModulator::interpolation(float * in_buf, uint32_t in_samples, float * out_buf, uint32_t out_samples, float last_in_samples[4]) { 44 | uint32_t i; /* Input buffer index + 1. */ 45 | uint32_t j = 0; /* Output buffer index. */ 46 | float pos; /* Position relative to the input buffer 47 | * + 1.0. */ 48 | 49 | /* We always "stay one sample behind", so what would be our first sample 50 | * should be the last one wrote by the previous call. */ 51 | pos = (float)in_samples / (float)out_samples; 52 | while (pos < 1.0) 53 | { 54 | out_buf[j] = last_in_samples[3] + (in_buf[0] - last_in_samples[3]) * pos; 55 | j++; 56 | pos = (float)(j + 1)* (float)in_samples / (float)out_samples; 57 | } 58 | 59 | /* Interpolation cycle. */ 60 | i = (uint32_t)pos; 61 | while (j < (out_samples - 1)) 62 | { 63 | 64 | out_buf[j] = in_buf[i - 1] + (in_buf[i] - in_buf[i - 1]) * (pos - (float)i); 65 | j++; 66 | pos = (float)(j + 1)* (float)in_samples / (float)out_samples; 67 | i = (uint32_t)pos; 68 | } 69 | 70 | /* The last sample is always the same in input and output buffers. */ 71 | out_buf[j] = in_buf[in_samples - 1]; 72 | 73 | /* Copy last samples to last_in_samples (reusing i and j). */ 74 | for (i = in_samples - 4, j = 0; j < 4; i++, j++) 75 | last_in_samples[j] = in_buf[i]; 76 | } 77 | 78 | void FMModulator::modulation(float * input, float * output, uint32_t mode) { 79 | if (mode == 0) { 80 | fm_deviation = 2.0 * M_PI * 75.0e3 / hackrf_sample; // 75 kHz max deviation WBFM 81 | } 82 | else if (mode == 1) 83 | { 84 | fm_deviation = 2.0 * M_PI * 5.0e3 / hackrf_sample; // 5 kHz max deviation NBFM 85 | } 86 | 87 | //AM mode 88 | if (mode == 2) { 89 | for (uint32_t i = 0; i < BUF_LEN; i++) { 90 | double audio_amp = input[i] * gain; 91 | 92 | if (fabs(audio_amp) > 1.0) { 93 | audio_amp = (audio_amp > 0.0) ? 1.0 : -1.0; 94 | } 95 | 96 | IQ_buf[i * BYTES_PER_SAMPLE] = (float)audio_amp; 97 | IQ_buf[i * BYTES_PER_SAMPLE + 1] = 0; 98 | } 99 | } 100 | //FM mode 101 | else { 102 | 103 | for (uint32_t i = 0; i < BUF_LEN; i++) { 104 | 105 | double audio_amp = input[i] * gain; 106 | 107 | if (fabs(audio_amp) > 1.0) { 108 | audio_amp = (audio_amp > 0.0) ? 1.0 : -1.0; 109 | } 110 | fm_phase += fm_deviation * audio_amp; 111 | while (fm_phase > (float)(M_PI)) 112 | fm_phase -= (float)(2.0 * M_PI); 113 | while (fm_phase < (float)(-M_PI)) 114 | fm_phase += (float)(2.0 * M_PI); 115 | 116 | output[i * BYTES_PER_SAMPLE] = (float)sin(fm_phase); 117 | output[i * BYTES_PER_SAMPLE + 1] = (float)cos(fm_phase); 118 | } 119 | } 120 | } 121 | 122 | void FMModulator::work(float *input_items, uint32_t len) { 123 | 124 | m_mutex.lock(); 125 | int8_t * buf = (int8_t *)_buf_ptr[head]; 126 | for (uint32_t i = 0; i < BUF_LEN; i++) { 127 | buf[i] = (int8_t)(input_items[i] * 127.0); 128 | } 129 | head = (head + 1) % BUF_NUM; 130 | count++; 131 | m_mutex.unlock(); 132 | 133 | } 134 | int FMModulator::onData(int8_t* buffer, uint32_t length) 135 | { 136 | m_mutex.lock(); 137 | 138 | if (count == 0) { 139 | memset(buffer, 0, length); 140 | } 141 | else { 142 | memcpy(buffer, _buf_ptr[tail], length); 143 | tail = (tail + 1) % BUF_NUM; 144 | count--; 145 | } 146 | m_mutex.unlock(); 147 | 148 | return 0; 149 | } 150 | 151 | void FMModulator::Start(WavSource *source) 152 | { 153 | int nch = source->getChannels(); 154 | m_sample_count = source->getSampleCount(); 155 | //hackrf_sample = m_sample_rate*1.0 / m_sample_count*BUF_LEN; 156 | 157 | float * source_audio_buf = source->getData(); 158 | 159 | if (!inited) { 160 | audio_buf = new float[m_sample_count](); 161 | new_audio_buf = new float[BUF_LEN](); 162 | IQ_buf = new float[BUF_LEN * BYTES_PER_SAMPLE](); 163 | inited = true; 164 | } 165 | 166 | if (nch == 1) { 167 | for (uint32_t i = 0; i < m_sample_count; i++) { 168 | 169 | audio_buf[i] = source_audio_buf[i]; 170 | } 171 | } 172 | else if (nch == 2) { 173 | for (uint32_t i = 0; i < m_sample_count; i++) { 174 | 175 | audio_buf[i] = (source_audio_buf[i * 2] + source_audio_buf[i * 2 + 1]) / (float)2.0; 176 | } 177 | } 178 | 179 | interpolation(audio_buf, m_sample_count, new_audio_buf, BUF_LEN, last_in_samples); 180 | 181 | modulation(new_audio_buf, IQ_buf, mode); 182 | 183 | for (uint32_t i = 0; i < (BUF_LEN * BYTES_PER_SAMPLE); i += BUF_LEN) { 184 | 185 | work(IQ_buf + i, BUF_LEN); 186 | } 187 | 188 | //AM mode 189 | } 190 | -------------------------------------------------------------------------------- /HackRF_Transmitter/HackRF_Transmitter.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {BD76BC64-68F9-470F-A778-593BC958D301} 23 | HackRF_Transmitter 24 | 8.1 25 | 26 | 27 | 28 | Application 29 | true 30 | v120 31 | Unicode 32 | 33 | 34 | Application 35 | false 36 | v120 37 | true 38 | Unicode 39 | 40 | 41 | Application 42 | true 43 | v120 44 | MultiByte 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | MultiByte 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Level3 75 | Disabled 76 | true 77 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 78 | MultiThreadedDebug 79 | F:\projects\HackRF_Transmitter;%(AdditionalIncludeDirectories) 80 | 81 | 82 | libhackrf.lib;Winmm.lib;%(AdditionalDependencies) 83 | F:\projects\HackRF_Transmitter\Debug;%(AdditionalLibraryDirectories) 84 | true 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | true 92 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 93 | 94 | 95 | libhackrf.lib;%(AdditionalDependencies) 96 | 97 | 98 | 99 | 100 | Level3 101 | MaxSpeed 102 | true 103 | true 104 | true 105 | 106 | 107 | true 108 | true 109 | 110 | 111 | 112 | 113 | Level3 114 | MaxSpeed 115 | true 116 | true 117 | true 118 | 119 | 120 | true 121 | true 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /HackRF_Transmitter/write_wav.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PortAudio Portable Real-Time Audio Library 3 | * Latest Version at: http://www.portaudio.com 4 | * 5 | * Copyright (c) 1999-2010 Phil Burk and Ross Bencina 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, 11 | * publish, distribute, sublicense, and/or sell copies of the Software, 12 | * and to permit persons to whom the Software is furnished to do so, 13 | * subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 22 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 23 | * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * The text above constitutes the entire PortAudio license; however, 29 | * the PortAudio community also makes the following non-binding requests: 30 | * 31 | * Any person wishing to distribute modifications to the Software is 32 | * requested to send the modifications to the original developer so that 33 | * they can be incorporated into the canonical version. It is also 34 | * requested that these non-binding requests be included along with the 35 | * license above. 36 | */ 37 | 38 | /** 39 | * Very simple WAV file writer for saving captured audio. 40 | */ 41 | #include 42 | #include 43 | #include "write_wav.h" 44 | 45 | 46 | /* Write long word data to a little endian format byte array. */ 47 | static void WriteLongLE( unsigned char **addrPtr, unsigned long data ) 48 | { 49 | unsigned char *addr = *addrPtr; 50 | *addr++ = (unsigned char) data; 51 | *addr++ = (unsigned char) (data>>8); 52 | *addr++ = (unsigned char) (data>>16); 53 | *addr++ = (unsigned char) (data>>24); 54 | *addrPtr = addr; 55 | } 56 | 57 | /* Write short word data to a little endian format byte array. */ 58 | static void WriteShortLE( unsigned char **addrPtr, unsigned short data ) 59 | { 60 | unsigned char *addr = *addrPtr; 61 | *addr++ = (unsigned char) data; 62 | *addr++ = (unsigned char) (data>>8); 63 | *addrPtr = addr; 64 | } 65 | 66 | /* Write IFF ChunkType data to a byte array. */ 67 | static void WriteChunkType( unsigned char **addrPtr, unsigned long cktyp ) 68 | { 69 | unsigned char *addr = *addrPtr; 70 | *addr++ = (unsigned char) (cktyp>>24); 71 | *addr++ = (unsigned char) (cktyp>>16); 72 | *addr++ = (unsigned char) (cktyp>>8); 73 | *addr++ = (unsigned char) cktyp; 74 | *addrPtr = addr; 75 | } 76 | 77 | #define WAV_HEADER_SIZE (4 + 4 + 4 + /* RIFF+size+WAVE */ \ 78 | 4 + 4 + 16 + /* fmt chunk */ \ 79 | 4 + 4 ) /* data chunk */ 80 | 81 | 82 | /********************************************************************************* 83 | * Open named file and write WAV header to the file. 84 | * The header includes the DATA chunk type and size. 85 | * Returns number of bytes written to file or negative error code. 86 | */ 87 | long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame ) 88 | { 89 | unsigned int bytesPerSecond; 90 | unsigned char header[ WAV_HEADER_SIZE ]; 91 | unsigned char *addr = header; 92 | int numWritten; 93 | 94 | writer->dataSize = 0; 95 | writer->dataSizeOffset = 0; 96 | 97 | writer->fid = fopen( fileName, "wb" ); 98 | if( writer->fid == NULL ) 99 | { 100 | return -1; 101 | } 102 | 103 | /* Write RIFF header. */ 104 | WriteChunkType( &addr, RIFF_ID ); 105 | 106 | /* Write RIFF size as zero for now. Will patch later. */ 107 | WriteLongLE( &addr, 0 ); 108 | 109 | /* Write WAVE form ID. */ 110 | WriteChunkType( &addr, WAVE_ID ); 111 | 112 | /* Write format chunk based on AudioSample structure. */ 113 | WriteChunkType( &addr, FMT_ID ); 114 | WriteLongLE( &addr, 16 ); 115 | WriteShortLE(&addr, WAVE_FORMAT_IEEE_FLOAT); 116 | bytesPerSecond = frameRate * samplesPerFrame * sizeof( short); 117 | WriteShortLE( &addr, (short) samplesPerFrame ); 118 | WriteLongLE( &addr, frameRate ); 119 | WriteLongLE( &addr, bytesPerSecond ); 120 | WriteShortLE( &addr, (short) (samplesPerFrame * sizeof( short)) ); /* bytesPerBlock */ 121 | WriteShortLE( &addr, (short) 32 ); /* bits per sample */ 122 | 123 | /* Write ID and size for 'data' chunk. */ 124 | WriteChunkType( &addr, DATA_ID ); 125 | /* Save offset so we can patch it later. */ 126 | writer->dataSizeOffset = (int) (addr - header); 127 | WriteLongLE( &addr, 0 ); 128 | 129 | numWritten = fwrite( header, 1, sizeof(header), writer->fid ); 130 | if( numWritten != sizeof(header) ) return -1; 131 | 132 | return (int) numWritten; 133 | } 134 | 135 | /********************************************************************************* 136 | * Write to the data chunk portion of a WAV file. 137 | * Returns bytes written or negative error code. 138 | */ 139 | long Audio_WAV_WriteShorts( WAV_Writer *writer, 140 | short *samples, 141 | int numSamples 142 | ) 143 | { 144 | unsigned char buffer[2]; 145 | unsigned char *bufferPtr; 146 | int i; 147 | short *p = samples; 148 | int numWritten; 149 | int bytesWritten; 150 | if( numSamples <= 0 ) 151 | { 152 | return -1; 153 | } 154 | 155 | for( i=0; ifid ); 160 | if( numWritten != sizeof(buffer) ) return -1; 161 | } 162 | bytesWritten = numSamples * sizeof(short); 163 | writer->dataSize += bytesWritten; 164 | return (int) bytesWritten; 165 | } 166 | 167 | /********************************************************************************* 168 | * Close WAV file. 169 | * Update chunk sizes so it can be read by audio applications. 170 | */ 171 | long Audio_WAV_CloseWriter( WAV_Writer *writer ) 172 | { 173 | unsigned char buffer[4]; 174 | unsigned char *bufferPtr; 175 | int numWritten; 176 | int riffSize; 177 | 178 | /* Go back to beginning of file and update DATA size */ 179 | int result = fseek( writer->fid, writer->dataSizeOffset, SEEK_SET ); 180 | if( result < 0 ) return result; 181 | 182 | bufferPtr = buffer; 183 | WriteLongLE( &bufferPtr, writer->dataSize ); 184 | numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid ); 185 | if( numWritten != sizeof(buffer) ) return -1; 186 | 187 | /* Update RIFF size */ 188 | result = fseek( writer->fid, 4, SEEK_SET ); 189 | if( result < 0 ) return result; 190 | 191 | riffSize = writer->dataSize + (WAV_HEADER_SIZE - 8); 192 | bufferPtr = buffer; 193 | WriteLongLE( &bufferPtr, riffSize ); 194 | numWritten = fwrite( buffer, 1, sizeof( buffer), writer->fid ); 195 | if( numWritten != sizeof(buffer) ) return -1; 196 | 197 | fclose( writer->fid ); 198 | writer->fid = NULL; 199 | return writer->dataSize; 200 | } 201 | 202 | /********************************************************************************* 203 | * Simple test that write a sawtooth waveform to a file. 204 | */ 205 | #if 0 206 | int main( void ) 207 | { 208 | int i; 209 | WAV_Writer writer; 210 | int result; 211 | #define NUM_SAMPLES (200) 212 | short data[NUM_SAMPLES]; 213 | short saw = 0; 214 | 215 | for( i=0; i 3 | Copyright (c) 2013, Benjamin Vernoux 4 | Copyright (c) 2013, Michael Ossmann 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 9 | 10 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | Neither the name of Great Scott Gadgets nor the names of its contributors may be used to endorse or promote products derived from this software 14 | without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 17 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 21 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | #ifndef __HACKRF_H__ 25 | #define __HACKRF_H__ 26 | 27 | #include 28 | 29 | #ifdef _WIN32 30 | #define ADD_EXPORTS 31 | 32 | /* You should define ADD_EXPORTS *only* when building the DLL. */ 33 | #ifdef ADD_EXPORTS 34 | #define ADDAPI __declspec(dllexport) 35 | #else 36 | #define ADDAPI __declspec(dllimport) 37 | #endif 38 | 39 | /* Define calling convention in one place, for convenience. */ 40 | #define ADDCALL __cdecl 41 | 42 | #else /* _WIN32 not defined. */ 43 | 44 | /* Define with no value on non-Windows OSes. */ 45 | #define ADDAPI 46 | #define ADDCALL 47 | 48 | #endif 49 | 50 | enum hackrf_error { 51 | HACKRF_SUCCESS = 0, 52 | HACKRF_TRUE = 1, 53 | HACKRF_ERROR_INVALID_PARAM = -2, 54 | HACKRF_ERROR_NOT_FOUND = -5, 55 | HACKRF_ERROR_BUSY = -6, 56 | HACKRF_ERROR_NO_MEM = -11, 57 | HACKRF_ERROR_LIBUSB = -1000, 58 | HACKRF_ERROR_THREAD = -1001, 59 | HACKRF_ERROR_STREAMING_THREAD_ERR = -1002, 60 | HACKRF_ERROR_STREAMING_STOPPED = -1003, 61 | HACKRF_ERROR_STREAMING_EXIT_CALLED = -1004, 62 | HACKRF_ERROR_OTHER = -9999, 63 | }; 64 | 65 | enum hackrf_board_id { 66 | BOARD_ID_JELLYBEAN = 0, 67 | BOARD_ID_JAWBREAKER = 1, 68 | BOARD_ID_HACKRF_ONE = 2, 69 | BOARD_ID_INVALID = 0xFF, 70 | }; 71 | 72 | enum hackrf_usb_board_id { 73 | USB_BOARD_ID_JAWBREAKER = 0x604B, 74 | USB_BOARD_ID_HACKRF_ONE = 0x6089, 75 | USB_BOARD_ID_RAD1O = 0xCC15, 76 | USB_BOARD_ID_INVALID = 0xFFFF, 77 | }; 78 | 79 | enum rf_path_filter { 80 | RF_PATH_FILTER_BYPASS = 0, 81 | RF_PATH_FILTER_LOW_PASS = 1, 82 | RF_PATH_FILTER_HIGH_PASS = 2, 83 | }; 84 | 85 | typedef enum { 86 | TRANSCEIVER_MODE_OFF = 0, 87 | TRANSCEIVER_MODE_RX = 1, 88 | TRANSCEIVER_MODE_TX = 2, 89 | TRANSCEIVER_MODE_SS = 3, 90 | TRANSCEIVER_MODE_CPLD_UPDATE = 4 91 | } transceiver_mode_t; 92 | 93 | typedef struct hackrf_device hackrf_device; 94 | 95 | typedef struct { 96 | hackrf_device* device; 97 | uint8_t* buffer; 98 | int buffer_length; 99 | int valid_length; 100 | void* rx_ctx; 101 | void* tx_ctx; 102 | } hackrf_transfer; 103 | 104 | typedef struct { 105 | uint32_t part_id[2]; 106 | uint32_t serial_no[4]; 107 | } read_partid_serialno_t; 108 | 109 | 110 | struct hackrf_device_list { 111 | char **serial_numbers; 112 | enum hackrf_usb_board_id *usb_board_ids; 113 | int *usb_device_index; 114 | int devicecount; 115 | 116 | void **usb_devices; 117 | int usb_devicecount; 118 | }; 119 | typedef struct hackrf_device_list hackrf_device_list_t; 120 | 121 | typedef int (*hackrf_sample_block_cb_fn)(hackrf_transfer* transfer); 122 | 123 | #ifdef __cplusplus 124 | extern "C" 125 | { 126 | #endif 127 | 128 | extern ADDAPI int ADDCALL hackrf_init(); 129 | extern ADDAPI int ADDCALL hackrf_exit(); 130 | 131 | extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list(); 132 | extern ADDAPI int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device); 133 | extern ADDAPI void ADDCALL hackrf_device_list_free(hackrf_device_list_t *list); 134 | 135 | extern ADDAPI int ADDCALL hackrf_open(hackrf_device** device); 136 | extern ADDAPI int ADDCALL hackrf_open_by_serial(const char* const desired_serial_number, hackrf_device** device); 137 | extern ADDAPI int ADDCALL hackrf_close(hackrf_device* device); 138 | 139 | extern ADDAPI int ADDCALL hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* rx_ctx); 140 | extern ADDAPI int ADDCALL hackrf_stop_rx(hackrf_device* device); 141 | 142 | extern ADDAPI int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* tx_ctx); 143 | extern ADDAPI int ADDCALL hackrf_stop_tx(hackrf_device* device); 144 | 145 | /* return HACKRF_TRUE if success */ 146 | extern ADDAPI int ADDCALL hackrf_is_streaming(hackrf_device* device); 147 | 148 | extern ADDAPI int ADDCALL hackrf_max2837_read(hackrf_device* device, uint8_t register_number, uint16_t* value); 149 | extern ADDAPI int ADDCALL hackrf_max2837_write(hackrf_device* device, uint8_t register_number, uint16_t value); 150 | 151 | extern ADDAPI int ADDCALL hackrf_si5351c_read(hackrf_device* device, uint16_t register_number, uint16_t* value); 152 | extern ADDAPI int ADDCALL hackrf_si5351c_write(hackrf_device* device, uint16_t register_number, uint16_t value); 153 | 154 | extern ADDAPI int ADDCALL hackrf_set_baseband_filter_bandwidth(hackrf_device* device, const uint32_t bandwidth_hz); 155 | 156 | extern ADDAPI int ADDCALL hackrf_rffc5071_read(hackrf_device* device, uint8_t register_number, uint16_t* value); 157 | extern ADDAPI int ADDCALL hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number, uint16_t value); 158 | 159 | extern ADDAPI int ADDCALL hackrf_spiflash_erase(hackrf_device* device); 160 | extern ADDAPI int ADDCALL hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* const data); 161 | extern ADDAPI int ADDCALL hackrf_spiflash_read(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* data); 162 | 163 | /* device will need to be reset after hackrf_cpld_write */ 164 | extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device, 165 | unsigned char* const data, const unsigned int total_length); 166 | 167 | extern ADDAPI int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value); 168 | extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length); 169 | 170 | extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz); 171 | extern ADDAPI int ADDCALL hackrf_set_freq_explicit(hackrf_device* device, 172 | const uint64_t if_freq_hz, const uint64_t lo_freq_hz, 173 | const enum rf_path_filter path); 174 | 175 | /* currently 8-20Mhz - either as a fraction, i.e. freq 20000000hz divider 2 -> 10Mhz or as plain old 10000000hz (double) 176 | preferred rates are 8, 10, 12.5, 16, 20Mhz due to less jitter */ 177 | extern ADDAPI int ADDCALL hackrf_set_sample_rate_manual(hackrf_device* device, const uint32_t freq_hz, const uint32_t divider); 178 | extern ADDAPI int ADDCALL hackrf_set_sample_rate(hackrf_device* device, const double freq_hz); 179 | 180 | /* external amp, bool on/off */ 181 | extern ADDAPI int ADDCALL hackrf_set_amp_enable(hackrf_device* device, const uint8_t value); 182 | 183 | extern ADDAPI int ADDCALL hackrf_board_partid_serialno_read(hackrf_device* device, read_partid_serialno_t* read_partid_serialno); 184 | 185 | /* range 0-40 step 8d, IF gain in osmosdr */ 186 | extern ADDAPI int ADDCALL hackrf_set_lna_gain(hackrf_device* device, uint32_t value); 187 | 188 | /* range 0-62 step 2db, BB gain in osmosdr */ 189 | extern ADDAPI int ADDCALL hackrf_set_vga_gain(hackrf_device* device, uint32_t value); 190 | 191 | /* range 0-47 step 1db */ 192 | extern ADDAPI int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t value); 193 | 194 | /* antenna port power control */ 195 | extern ADDAPI int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value); 196 | 197 | extern ADDAPI const char* ADDCALL hackrf_error_name(enum hackrf_error errcode); 198 | extern ADDAPI const char* ADDCALL hackrf_board_id_name(enum hackrf_board_id board_id); 199 | extern ADDAPI const char* ADDCALL hackrf_usb_board_id_name(enum hackrf_usb_board_id usb_board_id); 200 | extern ADDAPI const char* ADDCALL hackrf_filter_path_name(const enum rf_path_filter path); 201 | 202 | /* Compute nearest freq for bw filter (manual filter) */ 203 | extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(const uint32_t bandwidth_hz); 204 | /* Compute best default value depending on sample rate (auto filter) */ 205 | extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz); 206 | 207 | #ifdef __cplusplus 208 | } // __cplusplus defined. 209 | #endif 210 | 211 | #endif /*__HACKRF_H__*/ 212 | -------------------------------------------------------------------------------- /HackRF_Transmitter/input.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * FAAC - Freeware Advanced Audio Coder 3 | * Copyright (C) 2002 Krzysztof Nikiel 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * $Id: input.c,v 1.16 2009/01/25 18:50:32 menno Exp $ 20 | */ 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef _WIN32 30 | #include 31 | #include 32 | #endif 33 | 34 | #include "input.h" 35 | 36 | #define SWAP32(x) (((x & 0xff) << 24) | ((x & 0xff00) << 8) \ 37 | | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24)) 38 | #define SWAP16(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8)) 39 | 40 | #ifdef WORDS_BIGENDIAN 41 | # define UINT32(x) SWAP32(x) 42 | # define UINT16(x) SWAP16(x) 43 | #else 44 | # define UINT32(x) (x) 45 | # define UINT16(x) (x) 46 | #endif 47 | 48 | typedef struct 49 | { 50 | u_int32_t label; /* 'RIFF' */ 51 | u_int32_t length; /* Length of rest of file */ 52 | u_int32_t chunk_type; /* 'WAVE' */ 53 | } 54 | riff_t; 55 | 56 | typedef struct 57 | { 58 | u_int32_t label; 59 | u_int32_t len; 60 | } 61 | riffsub_t; 62 | 63 | #ifdef _MSC_VER 64 | #pragma pack(push, 1) 65 | #endif 66 | 67 | #define WAVE_FORMAT_PCM 1 68 | #define WAVE_FORMAT_FLOAT 3 69 | #define WAVE_FORMAT_EXTENSIBLE 0xfffe 70 | struct WAVEFORMATEX 71 | { 72 | u_int16_t wFormatTag; 73 | u_int16_t nChannels; 74 | u_int32_t nSamplesPerSec; 75 | u_int32_t nAvgBytesPerSec; 76 | u_int16_t nBlockAlign; 77 | u_int16_t wBitsPerSample; 78 | u_int16_t cbSize; 79 | } 80 | #ifdef __GNUC 81 | __attribute__((packed)) 82 | #endif 83 | ; 84 | 85 | struct WAVEFORMATEXTENSIBLE 86 | { 87 | struct WAVEFORMATEX Format; 88 | union { 89 | u_int16_t wValidBitsPerSample; // bits of precision 90 | u_int16_t wSamplesPerBlock; // valid if wBitsPerSample==0 91 | u_int16_t wReserved; // If neither applies, set to zero. 92 | } Samples; 93 | u_int32_t dwChannelMask; // which channels are present in stream 94 | unsigned char SubFormat[16]; // guid 95 | } 96 | #ifdef __GNUC 97 | __attribute__((packed)) 98 | #endif 99 | ; 100 | 101 | #ifdef _MSC_VER 102 | #pragma pack(pop) 103 | #endif 104 | 105 | static unsigned char waveformat_pcm_guid[16] = 106 | { 107 | WAVE_FORMAT_PCM,0,0,0, 108 | 0x00, 0x00, 109 | 0x10, 0x00, 110 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 111 | }; 112 | 113 | static void unsuperr(const char *name) 114 | { 115 | fprintf(stderr, "%s: file format not supported\n", name); 116 | } 117 | 118 | pcmfile_t *wav_open_read(const char *name, int rawinput) 119 | { 120 | int i; 121 | int skip; 122 | FILE *wave_f; 123 | riff_t riff; 124 | riffsub_t riffsub; 125 | struct WAVEFORMATEXTENSIBLE wave; 126 | char *riffl = "RIFF"; 127 | char *wavel = "WAVE"; 128 | char *bextl = "BEXT"; 129 | char *fmtl = "fmt "; 130 | char *datal = "data"; 131 | int fmtsize; 132 | pcmfile_t *sndf; 133 | int dostdin = 0; 134 | 135 | if (!strcmp(name, "-")) 136 | { 137 | #ifdef _WIN32 138 | _setmode(_fileno(stdin), O_BINARY); 139 | #endif 140 | wave_f = stdin; 141 | dostdin = 1; 142 | } 143 | else if (!(wave_f = fopen(name, "rb"))) 144 | { 145 | perror(name); 146 | return NULL; 147 | } 148 | 149 | if (!rawinput) // header input 150 | { 151 | if (fread(&riff, 1, sizeof(riff), wave_f) != sizeof(riff)) 152 | return NULL; 153 | if (memcmp(&(riff.label), riffl, 4)) 154 | return NULL; 155 | if (memcmp(&(riff.chunk_type), wavel, 4)) 156 | return NULL; 157 | 158 | // handle broadcast extensions. added by pro-tools,otherwise it must be fmt chunk. 159 | if (fread(&riffsub, 1, sizeof(riffsub), wave_f) != sizeof(riffsub)) 160 | return NULL; 161 | riffsub.len = UINT32(riffsub.len); 162 | 163 | if (!memcmp(&(riffsub.label), bextl, 4)) 164 | { 165 | fseek(wave_f, riffsub.len, SEEK_CUR); 166 | 167 | if (fread(&riffsub, 1, sizeof(riffsub), wave_f) != sizeof(riffsub)) 168 | return NULL; 169 | riffsub.len = UINT32(riffsub.len); 170 | } 171 | 172 | if (memcmp(&(riffsub.label), fmtl, 4)) 173 | return NULL; 174 | memset(&wave, 0, sizeof(wave)); 175 | 176 | fmtsize = (riffsub.len < sizeof(wave)) ? riffsub.len : sizeof(wave); 177 | if (fread(&wave, 1, fmtsize, wave_f) != fmtsize) 178 | return NULL; 179 | 180 | for (skip = riffsub.len - fmtsize; skip > 0; skip--) 181 | fgetc(wave_f); 182 | 183 | for (i = 0;; i++) 184 | { 185 | if (fread(&riffsub, 1, sizeof(riffsub), wave_f) != sizeof(riffsub)) 186 | return NULL; 187 | riffsub.len = UINT32(riffsub.len); 188 | if (!memcmp(&(riffsub.label), datal, 4)) 189 | break; 190 | if (i > 10) 191 | return NULL; 192 | 193 | for (skip = riffsub.len; skip > 0; skip--) 194 | fgetc(wave_f); 195 | } 196 | if (UINT16(wave.Format.wFormatTag) != WAVE_FORMAT_PCM && UINT16(wave.Format.wFormatTag) != WAVE_FORMAT_FLOAT) 197 | { 198 | if (UINT16(wave.Format.wFormatTag) == WAVE_FORMAT_EXTENSIBLE) 199 | { 200 | if (UINT16(wave.Format.cbSize) < 22) // struct too small 201 | return NULL; 202 | if (memcmp(wave.SubFormat, waveformat_pcm_guid, 16)) 203 | { 204 | waveformat_pcm_guid[0] = WAVE_FORMAT_FLOAT; 205 | if (memcmp(wave.SubFormat, waveformat_pcm_guid, 16)) 206 | { 207 | unsuperr(name); 208 | return NULL; 209 | } 210 | } 211 | } 212 | else 213 | { 214 | unsuperr(name); 215 | return NULL; 216 | } 217 | } 218 | } 219 | 220 | sndf = (pcmfile_t*)malloc(sizeof(*sndf)); 221 | memset(sndf, 0, sizeof(*sndf)); 222 | sndf->f = wave_f; 223 | 224 | if (UINT16(wave.Format.wFormatTag) == WAVE_FORMAT_FLOAT) { 225 | sndf->isfloat = 1; 226 | } else { 227 | sndf->isfloat = (wave.SubFormat[0] == WAVE_FORMAT_FLOAT); 228 | } 229 | if (rawinput) 230 | { 231 | sndf->bigendian = 1; 232 | if (dostdin) 233 | sndf->samples = 0; 234 | else 235 | { 236 | fseek(sndf->f, 0 , SEEK_END); 237 | sndf->samples = ftell(sndf->f); 238 | rewind(sndf->f); 239 | } 240 | } 241 | else 242 | { 243 | sndf->bigendian = 0; 244 | sndf->channels = UINT16(wave.Format.nChannels); 245 | sndf->samplebytes = UINT16(wave.Format.wBitsPerSample) / 8; 246 | sndf->samplerate = UINT32(wave.Format.nSamplesPerSec); 247 | sndf->samples = riffsub.len / (sndf->samplebytes * sndf->channels); 248 | } 249 | return sndf; 250 | } 251 | 252 | 253 | static void chan_remap(int32_t *buf, int channels, int blocks, int *map) 254 | { 255 | int i; 256 | int32_t *tmp = (int32_t*)malloc(channels * sizeof(int32_t)); 257 | 258 | for (i = 0; i < blocks; i++) 259 | { 260 | int chn; 261 | 262 | memcpy(tmp, buf + i * channels, sizeof(int32_t) * channels); 263 | 264 | for (chn = 0; chn < channels; chn++) 265 | buf[i * channels + chn] = tmp[map[chn]]; 266 | } 267 | } 268 | 269 | size_t wav_read_float32(pcmfile_t *sndf, float *buf, size_t num, int *map) 270 | { 271 | size_t i = 0; 272 | unsigned char bufi[8]; 273 | 274 | if ((sndf->samplebytes > 8) || (sndf->samplebytes < 1)) 275 | return 0; 276 | 277 | while (isamplebytes, 1, sndf->f) != 1) 279 | break; 280 | 281 | if (sndf->isfloat) 282 | { 283 | switch (sndf->samplebytes) { 284 | case 4: 285 | buf[i] = (*(float *)&bufi) * (float)32768; 286 | break; 287 | 288 | case 8: 289 | buf[i] = (float)((*(double *)&bufi) * (float)32768); 290 | break; 291 | 292 | default: 293 | return 0; 294 | } 295 | } 296 | else 297 | { 298 | // convert to 32 bit float 299 | // fix endianness 300 | switch (sndf->samplebytes) { 301 | case 1: 302 | /* this is endian clean */ 303 | buf[i] = ((float)bufi[0] - 128) * (float)256; 304 | break; 305 | 306 | case 2: 307 | #ifdef WORDS_BIGENDIAN 308 | if (!sndf->bigendian) 309 | #else 310 | if (sndf->bigendian) 311 | #endif 312 | { 313 | // swap bytes 314 | int16_t s = ((int16_t *)bufi)[0]; 315 | s = SWAP16(s); 316 | buf[i] = (float)s / 65530; 317 | } 318 | else 319 | { 320 | // no swap 321 | int s = ((int16_t *)bufi)[0]; 322 | buf[i] = (float)s / 65530; 323 | } 324 | break; 325 | 326 | case 3: 327 | if (!sndf->bigendian) 328 | { 329 | int s = bufi[0] | (bufi[1] << 8) | (bufi[2] << 16); 330 | 331 | // fix sign 332 | if (s & 0x800000) 333 | s |= 0xff000000; 334 | 335 | buf[i] = (float)s / 256; 336 | } 337 | else // big endian input 338 | { 339 | int s = (bufi[0] << 16) | (bufi[1] << 8) | bufi[2]; 340 | 341 | // fix sign 342 | if (s & 0x800000) 343 | s |= 0xff000000; 344 | 345 | buf[i] = (float)s / 256; 346 | } 347 | break; 348 | 349 | case 4: 350 | #ifdef WORDS_BIGENDIAN 351 | if (!sndf->bigendian) 352 | #else 353 | if (sndf->bigendian) 354 | #endif 355 | { 356 | // swap bytes 357 | int s = *(int *)&bufi; 358 | buf[i] = (float)SWAP32(s) / 65536; 359 | } 360 | else 361 | { 362 | int s = *(int *)&bufi; 363 | buf[i] = (float)s / 65536; 364 | } 365 | break; 366 | 367 | default: 368 | return 0; 369 | } 370 | } 371 | i++; 372 | } 373 | 374 | if (map) 375 | chan_remap((int32_t *)buf, sndf->channels, i / sndf->channels, map); 376 | 377 | return i; 378 | } 379 | 380 | size_t wav_read_int24(pcmfile_t *sndf, int32_t *buf, size_t num, int *map) 381 | { 382 | int size; 383 | int i; 384 | unsigned char *bufi; 385 | 386 | if ((sndf->samplebytes > 4) || (sndf->samplebytes < 1)) 387 | return 0; 388 | 389 | bufi = (unsigned char *) (char *)buf + sizeof(*buf) * num - sndf->samplebytes * (num - 1) - sizeof(*buf); 390 | 391 | size = fread(bufi, sndf->samplebytes, num, sndf->f); 392 | 393 | if(sizesamplebytes) { 401 | case 1: 402 | /* this is endian clean */ 403 | for (i = 0; i < size; i++) 404 | buf[i] = (bufi[i] - 128) * 65536; 405 | break; 406 | 407 | case 2: 408 | #ifdef WORDS_BIGENDIAN 409 | if (!sndf->bigendian) 410 | #else 411 | if (sndf->bigendian) 412 | #endif 413 | { 414 | // swap bytes 415 | for (i = 0; i < size; i++) 416 | { 417 | int16_t s = ((int16_t *)bufi)[i]; 418 | 419 | s = SWAP16(s); 420 | 421 | buf[i] = ((u_int32_t)s) << 8; 422 | } 423 | } 424 | else 425 | { 426 | // no swap 427 | for (i = 0; i < size; i++) 428 | { 429 | int s = ((int16_t *)bufi)[i]; 430 | 431 | buf[i] = s << 8; 432 | } 433 | } 434 | break; 435 | 436 | case 3: 437 | if (!sndf->bigendian) 438 | { 439 | for (i = 0; i < size; i++) 440 | { 441 | int s = bufi[3 * i] | (bufi[3 * i + 1] << 8) | (bufi[3 * i + 2] << 16); 442 | 443 | // fix sign 444 | if (s & 0x800000) 445 | s |= 0xff000000; 446 | 447 | buf[i] = s; 448 | } 449 | } 450 | else // big endian input 451 | { 452 | for (i = 0; i < size; i++) 453 | { 454 | int s = (bufi[3 * i] << 16) | (bufi[3 * i + 1] << 8) | bufi[3 * i + 2]; 455 | 456 | // fix sign 457 | if (s & 0x800000) 458 | s |= 0xff000000; 459 | 460 | buf[i] = s; 461 | } 462 | } 463 | break; 464 | 465 | case 4: 466 | #ifdef WORDS_BIGENDIAN 467 | if (!sndf->bigendian) 468 | #else 469 | if (sndf->bigendian) 470 | #endif 471 | { 472 | // swap bytes 473 | for (i = 0; i < size; i++) 474 | { 475 | int s = buf[i]; 476 | 477 | buf[i] = SWAP32(s); 478 | } 479 | } 480 | break; 481 | } 482 | 483 | if (map) 484 | chan_remap(buf, sndf->channels, size / sndf->channels, map); 485 | 486 | return size; 487 | } 488 | 489 | size_t wav_read_int24_buf(pcmfile_t *sndf, int32_t *outbuf, size_t num, unsigned char *inputbuf) 490 | { 491 | size_t i=0,j=0; 492 | int16_t bufi; 493 | 494 | while(isamplebytes); 497 | j+=sndf->samplebytes; 498 | //int16_t s=((int16_t*)bufi)[0]; 499 | outbuf[i]= bufi << 8; 500 | i++; 501 | } 502 | return j; 503 | } 504 | 505 | int wav_close(pcmfile_t *sndf) 506 | { 507 | int i = fclose(sndf->f); 508 | free(sndf); 509 | return i; 510 | } 511 | --------------------------------------------------------------------------------