autohotkey soundset doesn't change mic - audio

I'm trying to set my microphone to 50% with autohotkey but it only sets my master volume. I've tried
SoundSet 1, Microphone, 50
but it doesn't work. I also tried all the numbers up to 6.

I actually wrote something for this a while ago on the AHK subreddit. You can use this to toggle your mic volume to 50%. Pressing it again will set the volume back to whatever the original value was.
Give it a shot. If it doesn't work, let me know.
If it does, then you can mark your question answered.
Set your mic volume to something easy to remember but not common like 77. This is a temporary step to get the right audio device. You can change this later.
Run this script. PProvost wrote this and it can be found in the AHK Docs, too.
Look for the volume level that's set to 77. Note the component type (should look like Master:1), control type (most likely Volume or Microphone), and the mixer (which varies on each system. Mine was 10.)
;=============== Set This Stuff ===============
; Get this info from PProvost's script. If you lose the URL later, it's:
; https://github.com/PProvost/AutoHotKey/blob/master/SoundCardAnalysis.ahk
; Component Type
compType := "Master:1"
; Control Type
conType := "Volume"
; Mixer Number
mixer := 10
;Toggle tracker
toggle := 0
;=============== End "Set This Stuff" Section ===============
; Hotkey to set/toggle volume
F1::
; Tracks sound status
toggle = !toggle
; If toggle is turned on
if (toggle = 1){
; Save old setting
SoundGet, oldSound, % compType, % conType, % mixer
; Set new setting
SoundSet, 50, % compType, % conType, % mixer
; If toggle is off
}Else
; Revert to the old setting
SoundSet, % oldSound, % compType, % conType, % mixer
return
; Shift+Escape kills the app.
+Escape::ExitApp

I made my owm AHK with the response's help. I set it in my startup file and it sets my microphone volume to 30% every time I start up my computer (since my microphone is standard pretty loud)
Here is the code:
;=============== sauce ===============
; https://stackoverflow.com/questions/44330795/autohotkey-soundset-doesnt-change-mic
; https://github.com/PProvost/AutoHotKey/blob/master/SoundCardAnalysis.ahk
; Component Type
compType := "MASTER:1"
; Control Type
conType := "VOLUME"
; Mixer Number
mixer := 7
SoundSet, 31, % compType, % conType, % mixer

Related

DPI aware screen capture

I used AutoIt's _ScreenCapture_Capture() before without any trouble. But on Windows 10 with a 4k resolution screen I'm using DPI scaling at 200%. _ScreenCapture_capture() now gets something 2x zoomed in and half the location I asked for.
For instance :
_ScreenCapture_Capture("c:\a.bmp", 100, 100, 200, 200)
; Path, X1, Y1, X2, Y2
Does not return a 100x100 pixel square of the screen (at 100,100 to 200,200). It returns a 100x100 pixel square (at 50,50 to 100,100) instead.
I did find a solution :
DllCall("User32.dll", "bool", "SetProcessDPIAware")
However this screws up the GUI looks. So I then found this code:
GUISetFont(8.5 * _GDIPlus_GraphicsGetDPIRatio()[0])
Func _GDIPlus_GraphicsGetDPIRatio($iDPIDef = 96)
Local $aResults[2] = [1, 1]
_GDIPlus_Startup()
Local $hGfx = _GDIPlus_GraphicsCreateFromHWND(0)
If #error Then Return SetError(1, #extended, $aResults)
#forcedef $__g_hGDIPDll, $ghGDIPDll
$aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0)
If #error Then Return SetError(2, #extended, $aResults)
Local $iDPI = $aResult[2]
Local $aresults[2] = [$iDPIDef / $iDPI, $iDPI / $iDPIDef]
_GDIPlus_GraphicsDispose($hGfx)
_GDIPlus_Shutdown()
Return $aresults
EndFunc ;==>_GDIPlus_GraphicsGetDPIRatio
Which works great for the GUI but doesn't help for _ScreenCapture_Capture() calls. Seems I can either have a good looking- or a functioning program, not both.
How could I combine these two solutions to get both a good GUI and a functioning program? If I knew how to do the opposite of :
DllCall("User32.dll", "bool", "SetProcessDPIAware")
Then when I need to capture a screen portion I could turn on compatibility, then immediately turn it off when done capturing. But I don't know how to 'UNsetprocessdpiaware'.
If you are using Windows 10 A update (10.0.14393) you can spin up a separate thread and make the thread alone Per Monitor DPI aware, and leave your main GUI as dpi unaware.
See
SetThreadDpiAwarenessContext function
If you are building using a version of visual studio before 2015 you can declare a pointer to the function prototype
DPI_AWARENESS_CONTEXT WINAPI SetThreadDpiAwarenessContext(
_In_ DPI_AWARENESS_CONTEXT dpiContext
);
and use GetProcAddress to test for the presence of the function before you call it. Anything in that thread will give you raw physical information if you used
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
Note that this function is not available on Windows 10 10.0.10586. You must test for its availability.

Linux ALSA Driver using channel count 3

Am running my ALSA Driver on Ubuntu 14.04, 64bit, 3.16.0-30-generic Kernel.
Hardware is proprietary hardware, hence cant give much details.
Following is the existing driver implementation:
Driver is provided sample format, sample rate, channel_count as input via module parameter. (Due to requirements need to provide inputs via module parameters)
Initial snd_pcm_hardware structure for playback path.
#define DEFAULT_PERIOD_SIZE (4096)
#define DEFAULT_NO_OF_PERIODS (1024)
static struct snd_pcm_hardware xxx_playback =
{
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_SYNC_START,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_8000 | \
SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_96000),
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,
.channels_max = 1,
.buffer_bytes_max = (DEFAULT_PERIOD_SIZE * DEFAULT_NO_OF_PERIODS),
.period_bytes_min = DEFAULT_PERIOD_SIZE,
.period_bytes_max = DEFAULT_PERIOD_SIZE,
.periods_min = DEFAULT_NO_OF_PERIODS,
.periods_max = DEFAULT_NO_OF_PERIODS,
};
Similar values for captures side snd_pcm_hardware structure.
Please, note that the following below values are replaced in playback open entry point, based on the current audio test configuration:
(user provides audio format, audio rate, ch count via module parameters as inputs to the driver, which are refilled in snd_pcm_hardware structure)
xxx_playback.formats = user_format_input
xxx_playback.rates = xxx_playback.rate_min, xxx_playback.rate_max = user_sample_rate_input
xxx_playback.channels_min = xxx_playback.channels_max = user_channel_input
Similarly values are re-filled for capture snd_pcm_hardware structure in capture open entry point.
Hardware is configured for clocks based on channel_count, format, sample_rate and driver registers successfully with ALSA layer
Found aplay/arecord working fine for channel_count = 1 or 2 or 4
During aplay/arecord, in driver when "runtime->channels" value is checked, it reflects the channel_count configured, which sounds correct to me.
Record data matches with played, since its a loop back test.
But when i use channel_count = 3, Both aplay or arecord reports
"Broken configuration for this PCM: no configurations available"!! for a wave file with channel_count '3'
ex: Playing WAVE './xxx.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Channels 3
ALSA lib pcm_params.c:2162:(snd1_pcm_hw_refine_slave) Slave PCM not usable
aplay: set_params:1204: Broken configuration for this PCM: no configurations available
With Following changes I was able to move ahead a bit:
.........................
Method1:
Driver is provided channel_count '3' as input via module parameter
Modified Driver to fill snd_pcm_hardware structure as payback->channels_min = 2 & playback->channels_min = 3; Similar values for capture path
aplay/arecord reports as 'channel count not available', though the wave file in use has 3 channels
ex: aplay -D hw:CARD=xxx,DEV=0 ./xxx.wav Playing WAVE './xxx.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Channels 3
aplay: set_params:1239: Channels count non available
Tried aplay/arecord with plughw, and aplay/arecord moved ahead
arecord -D plughw:CARD=xxx,DEV=0 -d 3 -f S16_LE -r 48000 -c 3 ./xxx_rec0.wav
aplay -D plughw:CARD=xxx,DEV=0 ./xxx.wav
Recording WAVE './xxx_rec0.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Channels 3
Playing WAVE './xxx.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Channels 3
End of Test
During aplay/arecord, In driver when "runtime->channels" value is checked it returns value 2!!! But played wavefile has ch count 3...
When data in recorded file is checked its all silence
.........................
Method2:
Driver is provided channel_count '3' as input via module parameter
Modified Driver to fill snd_pcm_hardware structure as playback->channels_min = 3 & playback->channels_min = 4; Similar values for capture path
aplay/arecord reports as 'channel count not available', though the wave file in use has 3 channels
Tried aplay/arecord with plughw, and aplay/arecord moved ahead
During aplay/arecord, In driver when "runtime->channels" value is checked it returns value 4!!! But played wavefile has ch count 3...
When data in recorded file is checked its all silence
.........................
So from above observations, the runtime->channels is either 2 or 4, but never 3 channels was used by alsa stack though requested. When used Plughw, alsa is converting data to run under 2 or 4 channel.
Can anyone help why am unable to use channel count 3.
Will provide more information if needed.
Thanks in Advance.
A period (and the entire buffer) must contain an integral number of frames, i.e., you cannot have partial frames.
With three channels, one frame has six bytes. The fixed period size (4096) is not divisible by six without remainder.
Thanks CL.
I used period size 4092 for this particular test case with channel count 3, and was able to do loop back successfully (without using plughw).
One last question, when I used plughw earlier, and when runtime->channels was either 2 or 4, why was the recorded data not showing?

Qt 5.4 Linux Touchscreen Input with Tslib on Raspberry Pi failing with LinuxFB QPA Platform Plugin

I bought a Tontec 2.4 Inch Touchscreen ( http://elinux.org/MZTX-PI-EXT ) for my Raspberry Pi. The touchscreen controller requires the "tsc2007.ko" and "tsp_raspi.ko" kernel modules as described in the elinux post. The tsc2007.ko module is in the Raspbian Kernel tree but the tsp_raspi.ko can be found here: https://github.com/osandov/raspi/tree/master/tsc2007.
I've cross compiled a new Kernel for the Pi with those modules and they load fine and create a /dev/input/event0 device in Raspbian. If I 'evtest' that device and touch the screen, I get output so I know the events are being delivered in Linux:
pi#raspberry /dev/input $ evtest
Available devices:
/dev/input/event0: TSC2007 Touchscreen
Select the device event number [0-0]: 0
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0
Input device name: "TSC2007 Touchscreen"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 330 (BTN_TOUCH)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 1922
Min 0
Max 4095
Fuzz 64
Event code 1 (ABS_Y)
Value 2221
Min 0
Max 4095
Fuzz 64
Event code 24 (ABS_PRESSURE)
Value 0
Min 0
Max 4095
Fuzz 64
Properties:
Testing ... (interrupt to exit)
Event: time 1425521704.199489, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1425521704.199489, type 3 (EV_ABS), code 1 (ABS_Y), value 2085
Event: time 1425521704.199489, type 3 (EV_ABS), code 24 (ABS_PRESSURE), value 538
Event: time 1425521704.199489, -------------- SYN_REPORT ------------
Event: time 1425521704.209174, type 3 (EV_ABS), code 0 (ABS_X), value 1455
...
I installed tslib and ran a quick ts_calibrate. I also made sure that ts_test spit out data when I touched the screen.
I added the following environment variables to /etc/profile for tslib support in Qt5:
## For Qt5 Touchscreen Support
export QT_DEBUG_PLUGINS=1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/arm-linux-gnueabihf/
export QT_PLUGIN_PATH=/usr/lib/plugins
export QT_QPA_FONTDIR=/usr/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/plugins/platforms
export QT_QPA_PLATFORM=linuxfb
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event0
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0
export TSLIB_TSEVENTTYPE='INPUT'
export TSLIB_CALIBFILE='/etc/pointercal'
export TSLIB_CONFFILE='/etc/ts.conf'
export TSLIB_CONSOLEDEVICE='none'
export TSLIB_FBDEVICE='/dev/fb0'
export TSLIB_PLUGINDIR='/usr/lib/ts'
export TSLIB_TSDEVICE='/dev/input/event0'
I read up on the Qt5 docs and how to get touch events in my app. I have a main Widget and set the appropriate flags in the constructor:
MainWidget::MainWidget(QLabel *parent)
: QLabel(parent)
{
qDebug() << "Setting WA_AcceptTouchEvents on MainWidget...";
// Accept touch events
setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_StaticContents);
}
I setup an event filter to try to catch the touch events:
bool MainWidget::eventFilter( QObject* target, QEvent* e )
{
qDebug() << "Event Type: " << e->type();
return false;
return QLabel::eventFilter(target, e);
}
I launch my app like this:
myapp -platform linuxfb:fb=/dev/fb0 -plugin tslib:/dev/input/event0
I also uncommented a single printf in Qt's source code for the qtslib.cpp:
void QTsLibMouseHandler::readMouseData()
{
ts_sample sample;
while (get_sample(m_dev, &sample, m_rawMode)) {
bool pressed = sample.pressure;
int x = sample.x;
int y = sample.y;
// work around missing coordinates on mouse release
if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) {
x = m_x;
y = m_y;
}
if (!m_rawMode) {
//filtering: ignore movements of 2 pixels or less
int dx = x - m_x;
int dy = y - m_y;
if (dx*dx <= 4 && dy*dy <= 4 && pressed == m_pressed)
continue;
}
QPoint pos(x, y);
//printf("handleMouseEvent %d %d %d %ld\n", m_x, m_y, pressed, sample.tv.tv_usec);
QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton);
m_x = x;
m_y = y;
m_pressed = pressed;
}
}
When I launch my Qt app I see the plugins are loading OK ( even shows the correct event0 file ). I also see that the qt tslib plugin is receiving touch events when I touch the screen. The problem is that the event filter is NEVER called!
Here is the app being launched:
Got keys from plugin meta data ("tslib", "tslibraw")
QFactoryLoader::QFactoryLoader() checking directory path "/home/pi/generic" ...
loaded library "/usr/lib/qt/plugins/generic/libqtslibplugin.so"
QTsLibMouseHandler "tslib" ""
QTsLibMouseHandler "tslib" "/dev/input/event0"
QFactoryLoader::QFactoryLoader() checking directory path "/usr/lib/qt/plugins/styles" ...
QFactoryLoader::QFactoryLoader() checking directory path "/home/pi/styles" ...
Setting WA_AcceptTouchEvents on MainWidget...
-----------------------------------------
Waiting for data now...
-----------------------------------------
handleMouseEvent 0 0 1 751196
handleMouseEvent 0 0 1 751196
handleMouseEvent 1696 1615 1 771075
handleMouseEvent 1696 1615 1 771075
handleMouseEvent 1679 1622 1 781368
handleMouseEvent 1671 1638 1 781368
handleMouseEvent 1679 1622 1 781368
handleMouseEvent 1671 1638 1 781368
...
I found a few forum posts where people are having problems with touch input with the linuxfb platform plugin:
http://comments.gmane.org/gmane.comp.lib.qt.user/5686
http://qt-project.org/forums/viewthread/35757
http://qt-project.org/forums/viewthread/36120/
I've tried all their suggestions and still have the problem - no touch events are received by my app even though the Qt tslib plugin says it is receiving them.
It seems that the tslib plugin is having problems injecting the event it receives into my app's event loop with this:
QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton);
I also tried the Qt5.4 touch fingerpaint example and see the same behavior - no touch events are received.
I'm not sure where to go from here. I would greatly appreciate any help solving this issue. Thanks!
UPDATE:
I changed my event filter so it looks like this:
bool MainWidget::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "Event received" << obj->metaObject()->className() << event->type();
switch (event->type()) {
case QEvent::TouchBegin:
qDebug() << "TouchBegin";
case QEvent::TouchUpdate:
qDebug() << "TouchUpdate";
case QEvent::TouchEnd:
qDebug() << "TouchEnd";
{
// QTouchEvent *touch = static_cast<QTouchEvent *>(event);
// QList<QTouchEvent::TouchPoint> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
// foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) {
// switch (touchPoint.state()) {
// case Qt::TouchPointStationary:
// // don't do anything if this touch point hasn't moved
// continue;
// default:
// {
// }
// break;
// }
// }
// break;
}
//default:
//return QLabel::event(event);
}
//return true;
}
Now I can see 'socket notifier' events intermingled with Qt Tslib Plugin's prints whenever I touch the screen. Any ideas as to why Event Type 50 but no Touch Events?
Event received QSocketNotifier 50
handleMouseEvent 2702 2618 0 557715
Event received QSocketNotifier 50
handleMouseEvent 2698 2612 1 547758
Event received QSocketNotifier 50
handleMouseEvent 2706 2802 1 759928
Event received QSocketNotifier 50
Event received QSocketNotifier 50
UPDATE #2:
I installed the event filter only to try to catch any events. I'm not sure in Qt5 what translates an event type 50 ( QSocketNotifier ) to a QTouch* or QMouse* event.
Here is some more information:
When I run evtest, I see that the screen resolution is huge ( ~2500 x
~2500 ) and the actual screen is 320x240. I tried changed the
/dev/fb0 framebuffer size in /boot/config.txt to 320x240 and
rebooted. But the evtest and ts_calibrate steps still show the huge
resolution.
Because of the large resolution, I tried making my main widget
10000x10000 to see if I would get a touch or mouse event - but I
still only get the QSocketNotifier
I then tried to force the tslib plugin to always inject events at
screen position X=50 Y=50, but I still only get the event type 50
QSocketNotifier.
The problem was solved by making sure the tslib plugins were installed on the RasbperryPi.
TSLIB_PLUGINDIR=/usr/lib/ts
The directory /usr/lib/ts was not present on the Pi.

RaspBerry pi B rev2 - Issue while sampling a LM335 (temp. sensor) thru a MCP3208 ADC via SPI in Python 3

I tried to interface a RaspBerry pi with a LM335 temperature sensor this week-end. I'm using a MCP 3208 micro controller (channel 0) to interface the sensor. My goal is to collect samples data in SPI mode with python 3 scripts (classes).
I've checked the wiring and everything seems OK for me, I'but I'am a beginner, not really aware of Electronic concepts.
On the software side , I've installed quick2wire that claims to be python 3 compatible. In fact I want to lead the micro-controller with Python 3 API's (not thru shell calls)
Components
Raspberry pi REV2 model B with Rasbian-wheezy / Quick2wire installed. /dev/spix.y devices are listed.
MCP3208 ADC : 12 bits ADC / SPI. I'm using CS0 from the GPIO. The sensor is connected to channel 0 (B). see datasheet.
LM335 : temperature sensor. Outputs 10mV / °K. Min 5muA / Max 5 mA. It's connected to the MCP3208 channel #0 (A). see datasheet
220 ohms resistor (C). set up regarding LM335 outputs and desired temperature range coverage with my own calculations : May be a problem ...
Schematics extract
The LM335 (zener diode like) is connected as :
Wiring
Components are wired as shown bellow. Note that the yellow link is connected behind the cobbler kit on the CS0 SPI channel.
Quick2wire
I use the bellow script to query the CS0/Channel 0 GPIO interface. Unfortunately, I've not found usefull informations on the quick2wire-python-api API's. I've just copy/paste an example found as it was written in the same goal. I'm not sure if it really works :
#!/usr/bin/env python3
from quick2wire.spi import *
import sys, time
try:
channel = int(sys.argv[1])
except:
channel = 0
MCP3208 = SPIDevice(channel, 0)
while True:
try:
response = MCP3208.transaction(writing_bytes(0x41, 0x13), reading(1))
print ("output = %i" % ord(response[0]))
time.sleep(1)
except KeyboardInterrupt:
break
The script outputs :
output = 0
output = 0
output = 0
output = 0
output = 0
....
The result is the same with the channel 1 ( with argv = 1)
As the MCP3208 Din (probe output) receives voltage (see bellow) quick2wire should read at 18°C (rawghly my home inside temperature today)
3,3 V / 2^12 = 805 muA as I understand as "digital step"
18°C + 273°C = 291 => 2,91 V on the micro controller Din pin
and then return 2 910 / 0.805 = 3 615
Am I wrong ?
Controls
I've no oscilloscope, the only measures I can read are :
Voltage is 2.529 V at B checkpoint and 0,5 V (+/-5%) on the other MCP3208 channels
Note : the adjust pin is not used on the LM335 so results way not be accurate but voltage is here !
Seems to be a problem on the quick2wire side I think. But which ?
Code
The quick2wire.spi.SPIDevice class lakes of détails on the transfers parameter in terms of structure, content and output response format.
def transaction(self, *transfers):
"""
Perform an SPI I/O transaction.
Arguments:
*transfers -- SPI transfer requests created by one of the reading,
writing, writing_bytes, duplex or duplex_bytes
functions.
Returns: a list of byte sequences, one for each read or duplex
operation performed.
"""
transfer_count = len(transfers)
ioctl_arg = (spi_ioc_transfer*transfer_count)()
# populate array from transfers
for i, transfer in enumerate(transfers):
ioctl_arg[i] = transfers[i].to_spi_ioc_transfer()
ioctl(self.fd, SPI_IOC_MESSAGE(transfer_count), addressof(ioctl_arg))
return [transfer.to_read_bytes() for t in transfers if t.has_read_buf]
Another question :
how to set SPI configuration values like mode, clock speed, bits per word, LSB ... and so on.
Thanks in advance for your help.
I know you probably intend to learn how to use the ADC, an so this isn't really an answer to your question (I will use your very rich post for sure - thanks), but I'm aware of temperature sensors that already pack data in GPIO serial line, that are best suited for the raspberry.
You really have to read this awesome tutorial, if you haven't already.

Spatially Subsetting Images in batch mode using IDL and ENVI

I would like to spatially subset LANDSAT photos in ENVI using an IDL program. I have over 150 images that I would like to subset, so I'd like to run the program in batch mode (with no interaction). I know how to do it manually, but what command would I use to spatially subset the image via lat/long coordinates in IDL code?
Here is some inspiration, for a single file.
You can do the same for a large number of files by building up
a list of filenames and looping over it.
; define the image to be opened (could be in a loop), I believe it can also be a tif, img...
img_file='path/to/image.hdr'
envi_open_file,img_file,r_fid=fid
if (fid eq -1) then begin
print, 'Error when opening file ',img_file
return
endif
; let's define some coordinates
XMap=[-70.0580916, -70.5006694]
YMap=[-32.6030694, -32.9797194]
; now convert coordinates into pixel position:
; the transformation function uses the image geographic information:
ENVI_CONVERT_FILE_COORDINATES, FID, XF, YF, XMap, YMap
; we must consider integer. Think twice here, maybe you need to floor() or ceil()
XF=ROUND(XF)
YF=ROUND(YF)
; read the image
envi_file_query, fid, DIMS=DIMS, NB=NB, NL=NL, NS=NS
pos = lindgen(nb)
; and store it in an array
image=fltarr(NS, NL, NB)
; read each band sequentially
FOR i=0, NB-1 DO BEGIN
image[*,*,i]= envi_get_data(fid=fid, dims=dims, pos=pos[i])
endfor
; simply crop the data with array-indexing function
imagen= image[XF[0]:XF[1],YF[0]:YF[1]]
nl2=YF[1]-YF[0]
ns2=XF[1]-XF[0]
; read mapinfo to save it in the final file
map_info=envi_get_map_info(fid=fid)
envi_write_envi_file, imagen, data_type=4, $
descrip = 'cropped', $
map_info = map_info, $
nl=nl2, ns=ns2, nb=nb, r_fid=r_fid, $
OUT_NAME = 'path/to/cropped.hdr'

Resources